mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
spi: Updates for v7.2
This has been quite a busy release, mainly due to the subsystem wide
work Johan Hovold has done to modernise resource allocation for the
subsystem on probe, the subsystem did some very clever allocation
management pre devm which didn't quite mesh comfortably with managed
allocations and made it far too easy to introduce error handling and
removal bugs.
- Cleanup and simplification of controller struct allocation, moving
everything over to devm and making the devm APIs more robust, from
Johan Hovold
- Support for spi-mem devices that don't assert chip select and support
for a secondary read command for memory mapped flashes, some commits
for this are shared with mtd.
- Support for SpacemiT K1.
There will be a simple add/add conflict with the i2c-host tree in the
x86 quirk data in drivers/acpi/acpi_apd.c.
-----BEGIN PGP SIGNATURE-----
iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmowLx0ACgkQJNaLcl1U
h9BiuAf/bSzTrdeSLpQyQh/UxCKnl4joFtpyb9SValB/32oSTx9YecNYLDxA2z1L
3dkEPBRGBcGjGCINDQldJM/WMMRT0JKG58aWluF3YNPshKN7qK18iNQxbeN9Dh8F
qykmyWZ7wnLks03UCVm7be9kl2UHs4JJ+oRoHq0+6ktS7o+BrIzgJweprmTBmyB4
rRigCbPSL2BNBZnNvWqrZSYeqWHnonGYabhogaSJnhmeJTkSfKE6mugE8qmGzi+O
ZGeWsTdq270WU1omDZRy/PQQ3YLoLU2lUCGuHWTrT/98sGIJjkYV7UfE58GJwzpi
d1N+y8unL0R5HgSkMM4B+f/4OL3VoA==
=1zbv
-----END PGP SIGNATURE-----
Merge tag 'spi-v7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi updates from Mark Brown:
"This has been quite a busy release, mainly due to the subsystem wide
work Johan Hovold has done to modernise resource allocation for the
subsystem on probe, the subsystem did some very clever allocation
management pre devm which didn't quite mesh comfortably with managed
allocations and made it far too easy to introduce error handling and
removal bugs.
- Cleanup and simplification of controller struct allocation, moving
everything over to devm and making the devm APIs more robust, from
Johan Hovold
- Support for spi-mem devices that don't assert chip select and
support for a secondary read command for memory mapped flashes,
some commits for this are shared with mtd.
- Support for SpacemiT K1"
* tag 'spi-v7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (118 commits)
spi: Fix mismatched DT property access types
spi: xilinx: use FIFO occupancy register to determine buffer size
spi: spi-mem: Fix spi_controller_mem_ops kdoc
spi: xilinx: let transfers timeout in case of no IRQ
spi: dt-bindings: nuvoton,npcm750-fiu: Convert to DT schema
spi: meson-spifc: fix runtime PM leak on remove
spi: Use named initializers for platform_device_id arrays
spi: rzv2h-rspi: Add suspend/resume support
spi: dw-pci: remove redundant pci_free_irq_vectors() calls
spi: ep93xx: fix double-free of zeropage on DMA setup failure
spi: cadence-xspi: Revert COMPILE_TEST support
spi: cadence-xspi: Support 32bit and 64bit slave dma interface
spi: tegra210-quad: Allocate DMA memory for DMA engine
spi: imx: replace dmaengine_terminate_all() with dmaengine_terminate_sync()
spi: fsl-lpspi: terminate the RX channel on TX prepare failure path
spi: fsl-lpspi: replace dmaengine_terminate_all() with dmaengine_terminate_sync()
spi: atmel: fix DMA channel and bounce buffer leaks
spi: omap2-mcspi: Use of_device_get_match_data()
spi: Use named initializers for arrays of i2c_device_data
spi: aspeed: Replace VLA parameter with flat pointer in calibration helper
...
This commit is contained in:
commit
c41cfae42c
|
|
@ -1,58 +0,0 @@
|
|||
* Nuvoton FLASH Interface Unit (FIU) SPI Controller
|
||||
|
||||
NPCM FIU supports single, dual and quad communication interface.
|
||||
|
||||
The NPCM7XX supports three FIU modules,
|
||||
FIU0 and FIUx supports two chip selects,
|
||||
FIU3 support four chip select.
|
||||
|
||||
The NPCM8XX supports four FIU modules,
|
||||
FIU0 and FIUx supports two chip selects,
|
||||
FIU1 and FIU3 supports four chip selects.
|
||||
|
||||
Required properties:
|
||||
- compatible : "nuvoton,npcm750-fiu" for Poleg NPCM7XX BMC
|
||||
"nuvoton,npcm845-fiu" for Arbel NPCM8XX BMC
|
||||
- #address-cells : should be 1.
|
||||
- #size-cells : should be 0.
|
||||
- reg : the first contains the register location and length,
|
||||
the second contains the memory mapping address and length
|
||||
- reg-names: Should contain the reg names "control" and "memory"
|
||||
- clocks : phandle of FIU reference clock.
|
||||
|
||||
Required properties in case the pins can be muxed:
|
||||
- pinctrl-names : a pinctrl state named "default" must be defined.
|
||||
- pinctrl-0 : phandle referencing pin configuration of the device.
|
||||
|
||||
Optional property:
|
||||
- nuvoton,spix-mode: enable spix-mode for an expansion bus to an ASIC or CPLD.
|
||||
|
||||
Aliases:
|
||||
- All the FIU controller nodes should be represented in the aliases node using
|
||||
the following format 'fiu{n}' where n is a unique number for the alias.
|
||||
In the NPCM7XX BMC:
|
||||
fiu0 represent fiu 0 controller
|
||||
fiu1 represent fiu 3 controller
|
||||
fiu2 represent fiu x controller
|
||||
|
||||
In the NPCM8XX BMC:
|
||||
fiu0 represent fiu 0 controller
|
||||
fiu1 represent fiu 1 controller
|
||||
fiu2 represent fiu 3 controller
|
||||
fiu3 represent fiu x controller
|
||||
|
||||
Example:
|
||||
fiu3: spi@c00000000 {
|
||||
compatible = "nuvoton,npcm750-fiu";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0xfb000000 0x1000>, <0x80000000 0x10000000>;
|
||||
reg-names = "control", "memory";
|
||||
clocks = <&clk NPCM7XX_CLK_AHB>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&spi3_pins>;
|
||||
flash@0 {
|
||||
...
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/spi/nuvoton,npcm750-fiu.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Nuvoton NPCM Flash Interface Unit (FIU) SPI Controller
|
||||
|
||||
maintainers:
|
||||
- Tomer Maimon <tmaimon77@gmail.com>
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-controller.yaml#
|
||||
|
||||
description: |
|
||||
NPCM FIU supports single, dual and quad communication interface.
|
||||
|
||||
The NPCM7XX supports three FIU modules:
|
||||
FIU0 and FIUx support two chip selects
|
||||
FIU3 supports four chip selects.
|
||||
|
||||
The NPCM8XX supports four FIU modules:
|
||||
FIU0 and FIUx support two chip selects
|
||||
FIU1 and FIU3 support four chip selects.
|
||||
|
||||
The FIU control register block is always required. The direct-mapped
|
||||
flash window is optional because the controller can still access flash
|
||||
through the UMA path when that mapping is not described.
|
||||
|
||||
Alias convention:
|
||||
The '/aliases' node should define:
|
||||
For NPCM7xx: fiu0=&fiu0; fiu1=&fiu3; fiu2=&fiux;
|
||||
For NPCM8xx: fiu0=&fiu0; fiu1=&fiu3; fiu2=&fiux; fiu3=&fiu1;
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- nuvoton,npcm750-fiu # Poleg NPCM7XX
|
||||
- nuvoton,npcm845-fiu # Arbel NPCM8XX
|
||||
|
||||
reg:
|
||||
description:
|
||||
The first resource is the FIU control register block. An optional second
|
||||
resource describes the direct-mapped flash window used for direct
|
||||
read/write accesses.
|
||||
minItems: 1
|
||||
items:
|
||||
- description: FIU control registers
|
||||
- description: Memory-mapped flash contents
|
||||
|
||||
reg-names:
|
||||
description:
|
||||
Resource names for the control registers and optional direct-mapped
|
||||
flash window.
|
||||
minItems: 1
|
||||
items:
|
||||
- const: control
|
||||
- const: memory
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
description: FIU reference clock.
|
||||
|
||||
nuvoton,spix-mode:
|
||||
type: boolean
|
||||
description: Enable SPIX mode for an expansion bus to an ASIC or CPLD.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- clocks
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/nuvoton,npcm7xx-clock.h>
|
||||
spi@fb000000 {
|
||||
compatible = "nuvoton,npcm750-fiu";
|
||||
reg = <0xfb000000 0x1000>, <0x80000000 0x10000000>;
|
||||
reg-names = "control", "memory";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&clk NPCM7XX_CLK_SPI0>;
|
||||
|
||||
flash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
|
@ -13,13 +13,11 @@ description: The QSPI controller allows SPI protocol communication in single,
|
|||
dual, or quad wire transmission modes for read/write access to slaves such
|
||||
as NOR flash.
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- qcom,qcs615-qspi
|
||||
- qcom,sc7180-qspi
|
||||
- qcom,sc7280-qspi
|
||||
- qcom,sdm845-qspi
|
||||
|
|
@ -67,6 +65,23 @@ required:
|
|||
- clock-names
|
||||
- clocks
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-controller.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: qcom,qcs615-qspi
|
||||
then:
|
||||
properties:
|
||||
interconnects:
|
||||
minItems: 2
|
||||
interconnect-names:
|
||||
minItems: 2
|
||||
required:
|
||||
- interconnects
|
||||
- interconnect-names
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
|
|
|
|||
84
Documentation/devicetree/bindings/spi/spacemit,k1-spi.yaml
Normal file
84
Documentation/devicetree/bindings/spi/spacemit,k1-spi.yaml
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/spi/spacemit,k1-spi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: SpacemiT K1 SoC Serial Peripheral Interface (SPI)
|
||||
|
||||
maintainers:
|
||||
- Alex Elder <elder@kernel.org>
|
||||
|
||||
description:
|
||||
The SpacemiT K1 SoC implements a SPI controller that has two 32-entry
|
||||
FIFOs, for transmit and receive. Details are currently available in
|
||||
section 18.2.1 of the K1 User Manual, found in the SpacemiT Keystone
|
||||
K1 Documentation[1]. The controller transfers words using PIO. DMA
|
||||
transfers are supported as well, if both TX and RX DMA channels are
|
||||
specified,
|
||||
|
||||
[1] https://developer.spacemit.com/documentation
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: spacemit,k1-spi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Core clock
|
||||
- description: Bus clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
- const: bus
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
dmas:
|
||||
items:
|
||||
- description: RX DMA channel
|
||||
- description: TX DMA channel
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: rx
|
||||
- const: tx
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- interrupts
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
||||
#include <dt-bindings/clock/spacemit,k1-syscon.h>
|
||||
spi@d401c000 {
|
||||
compatible = "spacemit,k1-spi";
|
||||
reg = <0xd401c000 0x30>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&syscon_apbc CLK_SSP3>,
|
||||
<&syscon_apbc CLK_SSP3_BUS>;
|
||||
clock-names = "core", "bus";
|
||||
resets = <&syscon_apbc RESET_SSP3>;
|
||||
interrupts = <55>;
|
||||
dmas = <&pdma 20>, <&pdma 19>;
|
||||
dma-names = "rx", "tx";
|
||||
};
|
||||
|
|
@ -182,6 +182,11 @@ static const struct apd_device_desc hip08_spi_desc = {
|
|||
.fixed_clk_rate = 250000000,
|
||||
};
|
||||
|
||||
static const struct apd_device_desc leca_spi_desc = {
|
||||
.setup = acpi_apd_setup,
|
||||
.fixed_clk_rate = 400000000,
|
||||
};
|
||||
|
||||
static const struct apd_device_desc leca_i2c_desc = {
|
||||
.setup = acpi_apd_setup,
|
||||
.fixed_clk_rate = 250000000,
|
||||
|
|
@ -257,6 +262,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = {
|
|||
{ "HISI02A2", APD_ADDR(hip08_i2c_desc) },
|
||||
{ "HISI02A3", APD_ADDR(hip08_lite_i2c_desc) },
|
||||
{ "HISI0173", APD_ADDR(hip08_spi_desc) },
|
||||
{ "LECA0002", APD_ADDR(leca_spi_desc) },
|
||||
{ "LECA0003", APD_ADDR(leca_i2c_desc) },
|
||||
{ "NXP0001", APD_ADDR(nxp_i2c_desc) },
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -575,6 +575,7 @@ static void msi2500_disconnect(struct usb_interface *intf)
|
|||
v4l2_device_disconnect(&dev->v4l2_dev);
|
||||
video_unregister_device(&dev->vdev);
|
||||
spi_unregister_controller(dev->ctlr);
|
||||
spi_controller_put(dev->ctlr);
|
||||
mutex_unlock(&dev->v4l2_lock);
|
||||
mutex_unlock(&dev->vb_queue_lock);
|
||||
|
||||
|
|
@ -1230,10 +1231,8 @@ static int msi2500_probe(struct usb_interface *intf,
|
|||
ctlr->transfer_one_message = msi2500_transfer_one_message;
|
||||
spi_controller_set_devdata(ctlr, dev);
|
||||
ret = spi_register_controller(ctlr);
|
||||
if (ret) {
|
||||
spi_controller_put(ctlr);
|
||||
goto err_unregister_v4l2_dev;
|
||||
}
|
||||
if (ret)
|
||||
goto err_put_controller;
|
||||
|
||||
/* load v4l2 subdevice */
|
||||
sd = v4l2_spi_new_subdev(&dev->v4l2_dev, ctlr, &board_info);
|
||||
|
|
@ -1276,6 +1275,8 @@ static int msi2500_probe(struct usb_interface *intf,
|
|||
v4l2_ctrl_handler_free(&dev->hdl);
|
||||
err_unregister_controller:
|
||||
spi_unregister_controller(dev->ctlr);
|
||||
err_put_controller:
|
||||
spi_controller_put(dev->ctlr);
|
||||
err_unregister_v4l2_dev:
|
||||
v4l2_device_unregister(&dev->v4l2_dev);
|
||||
err_free_mem:
|
||||
|
|
|
|||
|
|
@ -501,10 +501,13 @@ static int spinand_read_from_cache_op(struct spinand_device *spinand,
|
|||
}
|
||||
}
|
||||
|
||||
if (req->mode == MTD_OPS_RAW)
|
||||
rdesc = spinand->dirmaps[req->pos.plane].rdesc;
|
||||
rdesc = spinand->dirmaps[req->pos.plane].rdesc;
|
||||
|
||||
if (nand->ecc.engine->integration == NAND_ECC_ENGINE_INTEGRATION_PIPELINED &&
|
||||
req->mode != MTD_OPS_RAW)
|
||||
rdesc->info.op_tmpl->data.ecc = true;
|
||||
else
|
||||
rdesc = spinand->dirmaps[req->pos.plane].rdesc_ecc;
|
||||
rdesc->info.op_tmpl->data.ecc = false;
|
||||
|
||||
if (spinand->flags & SPINAND_HAS_READ_PLANE_SELECT_BIT)
|
||||
column |= req->pos.plane << fls(nanddev_page_size(nand));
|
||||
|
|
@ -593,10 +596,13 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand,
|
|||
req->ooblen);
|
||||
}
|
||||
|
||||
if (req->mode == MTD_OPS_RAW)
|
||||
wdesc = spinand->dirmaps[req->pos.plane].wdesc;
|
||||
wdesc = spinand->dirmaps[req->pos.plane].wdesc;
|
||||
|
||||
if (nand->ecc.engine->integration == NAND_ECC_ENGINE_INTEGRATION_PIPELINED &&
|
||||
req->mode != MTD_OPS_RAW)
|
||||
wdesc->info.op_tmpl->data.ecc = true;
|
||||
else
|
||||
wdesc = spinand->dirmaps[req->pos.plane].wdesc_ecc;
|
||||
wdesc->info.op_tmpl->data.ecc = false;
|
||||
|
||||
if (spinand->flags & SPINAND_HAS_PROG_PLANE_SELECT_BIT)
|
||||
column |= req->pos.plane << fls(nanddev_page_size(nand));
|
||||
|
|
@ -892,6 +898,12 @@ static int spinand_mtd_continuous_page_read(struct mtd_info *mtd, loff_t from,
|
|||
* Each data read must be a multiple of 4-bytes and full pages should be read;
|
||||
* otherwise, the data output might get out of sequence from one read command
|
||||
* to another.
|
||||
*
|
||||
* Continuous reads never cross LUN boundaries. Some devices don't
|
||||
* support crossing planes boundaries. Some devices don't even support
|
||||
* crossing blocks boundaries. The common case being to read through UBI,
|
||||
* we will very rarely read two consequent blocks or more, so let's only enable
|
||||
* continuous reads when reading within the same erase block.
|
||||
*/
|
||||
nanddev_io_for_each_block(nand, NAND_PAGE_READ, from, ops, &iter) {
|
||||
ret = spinand_select_target(spinand, iter.req.pos.target);
|
||||
|
|
@ -982,19 +994,6 @@ static bool spinand_use_cont_read(struct mtd_info *mtd, loff_t from,
|
|||
nanddev_offs_to_pos(nand, from, &start_pos);
|
||||
nanddev_offs_to_pos(nand, from + ops->len - 1, &end_pos);
|
||||
|
||||
/*
|
||||
* Continuous reads never cross LUN boundaries. Some devices don't
|
||||
* support crossing planes boundaries. Some devices don't even support
|
||||
* crossing blocks boundaries. The common case being to read through UBI,
|
||||
* we will very rarely read two consequent blocks or more, so it is safer
|
||||
* and easier (can be improved) to only enable continuous reads when
|
||||
* reading within the same erase block.
|
||||
*/
|
||||
if (start_pos.target != end_pos.target ||
|
||||
start_pos.plane != end_pos.plane ||
|
||||
start_pos.eraseblock != end_pos.eraseblock)
|
||||
return false;
|
||||
|
||||
return start_pos.page < end_pos.page;
|
||||
}
|
||||
|
||||
|
|
@ -1252,12 +1251,18 @@ static int spinand_create_dirmap(struct spinand_device *spinand,
|
|||
struct nand_device *nand = spinand_to_nand(spinand);
|
||||
struct spi_mem_dirmap_info info = { 0 };
|
||||
struct spi_mem_dirmap_desc *desc;
|
||||
bool enable_ecc = false;
|
||||
|
||||
if (nand->ecc.engine->integration == NAND_ECC_ENGINE_INTEGRATION_PIPELINED)
|
||||
enable_ecc = true;
|
||||
|
||||
/* The plane number is passed in MSB just above the column address */
|
||||
info.offset = plane << fls(nand->memorg.pagesize);
|
||||
|
||||
/* Write descriptor */
|
||||
info.length = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand);
|
||||
info.op_tmpl = *spinand->op_templates->update_cache;
|
||||
info.primary_op_tmpl = *spinand->op_templates->update_cache;
|
||||
info.primary_op_tmpl.data.ecc = enable_ecc;
|
||||
desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev,
|
||||
spinand->spimem, &info);
|
||||
if (IS_ERR(desc))
|
||||
|
|
@ -1265,38 +1270,15 @@ static int spinand_create_dirmap(struct spinand_device *spinand,
|
|||
|
||||
spinand->dirmaps[plane].wdesc = desc;
|
||||
|
||||
info.op_tmpl = *spinand->op_templates->read_cache;
|
||||
/* Read descriptor */
|
||||
info.primary_op_tmpl = *spinand->op_templates->read_cache;
|
||||
info.primary_op_tmpl.data.ecc = enable_ecc;
|
||||
desc = spinand_create_rdesc(spinand, &info);
|
||||
if (IS_ERR(desc))
|
||||
return PTR_ERR(desc);
|
||||
|
||||
spinand->dirmaps[plane].rdesc = desc;
|
||||
|
||||
if (nand->ecc.engine->integration != NAND_ECC_ENGINE_INTEGRATION_PIPELINED) {
|
||||
spinand->dirmaps[plane].wdesc_ecc = spinand->dirmaps[plane].wdesc;
|
||||
spinand->dirmaps[plane].rdesc_ecc = spinand->dirmaps[plane].rdesc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
info.length = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand);
|
||||
info.op_tmpl = *spinand->op_templates->update_cache;
|
||||
info.op_tmpl.data.ecc = true;
|
||||
desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev,
|
||||
spinand->spimem, &info);
|
||||
if (IS_ERR(desc))
|
||||
return PTR_ERR(desc);
|
||||
|
||||
spinand->dirmaps[plane].wdesc_ecc = desc;
|
||||
|
||||
info.op_tmpl = *spinand->op_templates->read_cache;
|
||||
info.op_tmpl.data.ecc = true;
|
||||
desc = spinand_create_rdesc(spinand, &info);
|
||||
if (IS_ERR(desc))
|
||||
return PTR_ERR(desc);
|
||||
|
||||
spinand->dirmaps[plane].rdesc_ecc = desc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1421,7 +1403,7 @@ static void spinand_manufacturer_cleanup(struct spinand_device *spinand)
|
|||
return spinand->manufacturer->ops->cleanup(spinand);
|
||||
}
|
||||
|
||||
static bool spinand_op_is_odtr(const struct spi_mem_op *op)
|
||||
bool spinand_op_is_odtr(const struct spi_mem_op *op)
|
||||
{
|
||||
return op->cmd.dtr && op->cmd.buswidth == 8;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3641,14 +3641,15 @@ EXPORT_SYMBOL_GPL(spi_nor_scan);
|
|||
static int spi_nor_create_read_dirmap(struct spi_nor *nor)
|
||||
{
|
||||
struct spi_mem_dirmap_info info = {
|
||||
.op_tmpl = SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 0),
|
||||
SPI_MEM_OP_ADDR(nor->addr_nbytes, 0, 0),
|
||||
SPI_MEM_OP_DUMMY(nor->read_dummy, 0),
|
||||
SPI_MEM_OP_DATA_IN(0, NULL, 0)),
|
||||
.op_tmpl = &info.primary_op_tmpl,
|
||||
.primary_op_tmpl = SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 0),
|
||||
SPI_MEM_OP_ADDR(nor->addr_nbytes, 0, 0),
|
||||
SPI_MEM_OP_DUMMY(nor->read_dummy, 0),
|
||||
SPI_MEM_OP_DATA_IN(0, NULL, 0)),
|
||||
.offset = 0,
|
||||
.length = nor->params->size,
|
||||
};
|
||||
struct spi_mem_op *op = &info.op_tmpl;
|
||||
struct spi_mem_op *op = info.op_tmpl;
|
||||
|
||||
spi_nor_spimem_setup_op(nor, op, nor->read_proto);
|
||||
|
||||
|
|
@ -3672,14 +3673,15 @@ static int spi_nor_create_read_dirmap(struct spi_nor *nor)
|
|||
static int spi_nor_create_write_dirmap(struct spi_nor *nor)
|
||||
{
|
||||
struct spi_mem_dirmap_info info = {
|
||||
.op_tmpl = SPI_MEM_OP(SPI_MEM_OP_CMD(nor->program_opcode, 0),
|
||||
SPI_MEM_OP_ADDR(nor->addr_nbytes, 0, 0),
|
||||
SPI_MEM_OP_NO_DUMMY,
|
||||
SPI_MEM_OP_DATA_OUT(0, NULL, 0)),
|
||||
.op_tmpl = &info.primary_op_tmpl,
|
||||
.primary_op_tmpl = SPI_MEM_OP(SPI_MEM_OP_CMD(nor->program_opcode, 0),
|
||||
SPI_MEM_OP_ADDR(nor->addr_nbytes, 0, 0),
|
||||
SPI_MEM_OP_NO_DUMMY,
|
||||
SPI_MEM_OP_DATA_OUT(0, NULL, 0)),
|
||||
.offset = 0,
|
||||
.length = nor->params->size,
|
||||
};
|
||||
struct spi_mem_op *op = &info.op_tmpl;
|
||||
struct spi_mem_op *op = info.op_tmpl;
|
||||
|
||||
if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second)
|
||||
op->addr.nbytes = 0;
|
||||
|
|
|
|||
|
|
@ -1085,6 +1085,15 @@ config SPI_SG2044_NOR
|
|||
also supporting 3Byte address devices and 4Byte address
|
||||
devices.
|
||||
|
||||
config SPI_SPACEMIT_K1
|
||||
tristate "K1 SPI Controller"
|
||||
depends on ARCH_SPACEMIT || COMPILE_TEST
|
||||
depends on OF
|
||||
imply MMP_PDMA if ARCH_SPACEMIT
|
||||
default m if ARCH_SPACEMIT
|
||||
help
|
||||
Enable support for the SpacemiT K1 SPI controller.
|
||||
|
||||
config SPI_SPRD
|
||||
tristate "Spreadtrum SPI controller"
|
||||
depends on ARCH_SPRD || COMPILE_TEST
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ obj-$(CONFIG_SPI_SIFIVE) += spi-sifive.o
|
|||
obj-$(CONFIG_SPI_SLAVE_MT27XX) += spi-slave-mt27xx.o
|
||||
obj-$(CONFIG_SPI_SN_F_OSPI) += spi-sn-f-ospi.o
|
||||
obj-$(CONFIG_SPI_SG2044_NOR) += spi-sg2044-nor.o
|
||||
obj-$(CONFIG_SPI_SPACEMIT_K1) += spi-spacemit-k1.o
|
||||
obj-$(CONFIG_SPI_SPRD) += spi-sprd.o
|
||||
obj-$(CONFIG_SPI_SPRD_ADI) += spi-sprd-adi.o
|
||||
obj-$(CONFIG_SPI_STM32) += spi-stm32.o
|
||||
|
|
|
|||
|
|
@ -546,7 +546,7 @@ static int airoha_snand_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
|||
if (desc->info.length > SPI_NAND_CACHE_SIZE)
|
||||
return -E2BIG;
|
||||
|
||||
if (!airoha_snand_supports_op(desc->mem, &desc->info.op_tmpl))
|
||||
if (!airoha_snand_supports_op(desc->mem, desc->info.op_tmpl))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
|
|
@ -572,7 +572,7 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
|||
* DUALIO and QUADIO opcodes are not supported by the spi controller,
|
||||
* replace them with supported opcodes.
|
||||
*/
|
||||
opcode = desc->info.op_tmpl.cmd.opcode;
|
||||
opcode = desc->info.op_tmpl->cmd.opcode;
|
||||
switch (opcode) {
|
||||
case SPI_NAND_OP_READ_FROM_CACHE_SINGLE:
|
||||
case SPI_NAND_OP_READ_FROM_CACHE_SINGLE_FAST:
|
||||
|
|
@ -761,7 +761,7 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
|
|||
/* minimum oob size is 64 */
|
||||
bytes = round_up(offs + len, 64);
|
||||
|
||||
opcode = desc->info.op_tmpl.cmd.opcode;
|
||||
opcode = desc->info.op_tmpl->cmd.opcode;
|
||||
switch (opcode) {
|
||||
case SPI_NAND_OP_PROGRAM_LOAD_SINGLE:
|
||||
case SPI_NAND_OP_PROGRAM_LOAD_RAMDOM_SINGLE:
|
||||
|
|
|
|||
|
|
@ -39,12 +39,12 @@ static int altera_spi_probe(struct platform_device *pdev)
|
|||
enum altera_spi_type type = ALTERA_SPI_TYPE_UNKNOWN;
|
||||
struct altera_spi *hw;
|
||||
struct spi_controller *host;
|
||||
int err = -ENODEV;
|
||||
int err;
|
||||
u16 i;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(struct altera_spi));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(struct altera_spi));
|
||||
if (!host)
|
||||
return err;
|
||||
return -ENOMEM;
|
||||
|
||||
/* setup the host state. */
|
||||
host->bus_num = -1;
|
||||
|
|
@ -54,8 +54,7 @@ static int altera_spi_probe(struct platform_device *pdev)
|
|||
dev_err(&pdev->dev,
|
||||
"Invalid number of chipselect: %u\n",
|
||||
pdata->num_chipselect);
|
||||
err = -EINVAL;
|
||||
goto exit;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
host->num_chipselect = pdata->num_chipselect;
|
||||
|
|
@ -80,7 +79,7 @@ static int altera_spi_probe(struct platform_device *pdev)
|
|||
hw->regmap = dev_get_regmap(pdev->dev.parent, NULL);
|
||||
if (!hw->regmap) {
|
||||
dev_err(&pdev->dev, "get regmap failed\n");
|
||||
goto exit;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
regoff = platform_get_resource(pdev, IORESOURCE_REG, 0);
|
||||
|
|
@ -90,17 +89,14 @@ static int altera_spi_probe(struct platform_device *pdev)
|
|||
void __iomem *res;
|
||||
|
||||
res = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(res)) {
|
||||
err = PTR_ERR(res);
|
||||
goto exit;
|
||||
}
|
||||
if (IS_ERR(res))
|
||||
return PTR_ERR(res);
|
||||
|
||||
hw->regmap = devm_regmap_init_mmio(&pdev->dev, res,
|
||||
&spi_altera_config);
|
||||
if (IS_ERR(hw->regmap)) {
|
||||
dev_err(&pdev->dev, "regmap mmio init failed\n");
|
||||
err = PTR_ERR(hw->regmap);
|
||||
goto exit;
|
||||
return PTR_ERR(hw->regmap);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -112,12 +108,12 @@ static int altera_spi_probe(struct platform_device *pdev)
|
|||
err = devm_request_irq(&pdev->dev, hw->irq, altera_spi_irq, 0,
|
||||
pdev->name, host);
|
||||
if (err)
|
||||
goto exit;
|
||||
return err;
|
||||
}
|
||||
|
||||
err = devm_spi_register_controller(&pdev->dev, host);
|
||||
if (err)
|
||||
goto exit;
|
||||
return err;
|
||||
|
||||
if (pdata) {
|
||||
for (i = 0; i < pdata->num_devices; i++) {
|
||||
|
|
@ -131,9 +127,6 @@ static int altera_spi_probe(struct platform_device *pdev)
|
|||
dev_info(&pdev->dev, "regoff %u, irq %d\n", hw->regoff, hw->irq);
|
||||
|
||||
return 0;
|
||||
exit:
|
||||
spi_controller_put(host);
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
|
@ -146,8 +139,8 @@ MODULE_DEVICE_TABLE(of, altera_spi_match);
|
|||
#endif /* CONFIG_OF */
|
||||
|
||||
static const struct platform_device_id altera_spi_ids[] = {
|
||||
{ DRV_NAME, ALTERA_SPI_TYPE_UNKNOWN },
|
||||
{ "subdev_spi_altera", ALTERA_SPI_TYPE_SUBDEV },
|
||||
{ .name = DRV_NAME, .driver_data = ALTERA_SPI_TYPE_UNKNOWN },
|
||||
{ .name = "subdev_spi_altera", .driver_data = ALTERA_SPI_TYPE_SUBDEV },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, altera_spi_ids);
|
||||
|
|
|
|||
|
|
@ -206,10 +206,9 @@ static int amlogic_spifc_a1_read(struct amlogic_spifc_a1 *spifc, void *buf,
|
|||
u32 val = readl(spifc->base + SPIFC_A1_USER_CTRL3_REG);
|
||||
int ret;
|
||||
|
||||
val &= ~(SPIFC_A1_USER_DIN_MODE | SPIFC_A1_USER_DIN_BYTES);
|
||||
val |= SPIFC_A1_USER_DIN_ENABLE;
|
||||
val |= FIELD_PREP(SPIFC_A1_USER_DIN_MODE, mode);
|
||||
val |= FIELD_PREP(SPIFC_A1_USER_DIN_BYTES, size);
|
||||
FIELD_MODIFY(SPIFC_A1_USER_DIN_MODE, &val, mode);
|
||||
FIELD_MODIFY(SPIFC_A1_USER_DIN_BYTES, &val, size);
|
||||
writel(val, spifc->base + SPIFC_A1_USER_CTRL3_REG);
|
||||
|
||||
ret = amlogic_spifc_a1_request(spifc, true);
|
||||
|
|
|
|||
|
|
@ -258,8 +258,7 @@ static int aml_spisg_setup_transfer(struct spisg_device *spisg,
|
|||
int ret;
|
||||
|
||||
memset(desc, 0, sizeof(*desc));
|
||||
if (exdesc)
|
||||
memset(exdesc, 0, sizeof(*exdesc));
|
||||
memset(exdesc, 0, sizeof(*exdesc));
|
||||
aml_spisg_set_speed(spisg, xfer->speed_hz);
|
||||
xfer->effective_speed_hz = spisg->effective_speed_hz;
|
||||
|
||||
|
|
@ -601,14 +600,11 @@ static int aml_spisg_prepare_message(struct spi_controller *ctlr,
|
|||
|
||||
spisg->bytes_per_word = spi->bits_per_word >> 3;
|
||||
|
||||
spisg->cfg_spi &= ~CFG_SLAVE_SELECT;
|
||||
spisg->cfg_spi |= FIELD_PREP(CFG_SLAVE_SELECT, spi_get_chipselect(spi, 0));
|
||||
|
||||
spisg->cfg_bus &= ~(CFG_CPOL | CFG_CPHA | CFG_B_L_ENDIAN | CFG_HALF_DUPLEX);
|
||||
spisg->cfg_bus |= FIELD_PREP(CFG_CPOL, !!(spi->mode & SPI_CPOL)) |
|
||||
FIELD_PREP(CFG_CPHA, !!(spi->mode & SPI_CPHA)) |
|
||||
FIELD_PREP(CFG_B_L_ENDIAN, !!(spi->mode & SPI_LSB_FIRST)) |
|
||||
FIELD_PREP(CFG_HALF_DUPLEX, !!(spi->mode & SPI_3WIRE));
|
||||
FIELD_MODIFY(CFG_SLAVE_SELECT, &spisg->cfg_spi, spi_get_chipselect(spi, 0));
|
||||
FIELD_MODIFY(CFG_CPOL, &spisg->cfg_bus, !!(spi->mode & SPI_CPOL));
|
||||
FIELD_MODIFY(CFG_CPHA, &spisg->cfg_bus, !!(spi->mode & SPI_CPHA));
|
||||
FIELD_MODIFY(CFG_B_L_ENDIAN, &spisg->cfg_bus, !!(spi->mode & SPI_LSB_FIRST));
|
||||
FIELD_MODIFY(CFG_HALF_DUPLEX, &spisg->cfg_bus, !!(spi->mode & SPI_3WIRE));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -818,17 +818,13 @@ static int a3700_spi_probe(struct platform_device *pdev)
|
|||
u32 num_cs = 0;
|
||||
int irq, ret = 0;
|
||||
|
||||
host = spi_alloc_host(dev, sizeof(*spi));
|
||||
if (!host) {
|
||||
dev_err(dev, "host allocation failed\n");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
host = devm_spi_alloc_host(dev, sizeof(*spi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
if (of_property_read_u32(dev->of_node, "num-cs", &num_cs)) {
|
||||
dev_err(dev, "could not find num-cs\n");
|
||||
ret = -ENXIO;
|
||||
goto error;
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
host->bus_num = pdev->id;
|
||||
|
|
@ -849,25 +845,20 @@ static int a3700_spi_probe(struct platform_device *pdev)
|
|||
spi->host = host;
|
||||
|
||||
spi->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(spi->base)) {
|
||||
ret = PTR_ERR(spi->base);
|
||||
goto error;
|
||||
}
|
||||
if (IS_ERR(spi->base))
|
||||
return PTR_ERR(spi->base);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
ret = -ENXIO;
|
||||
goto error;
|
||||
}
|
||||
if (irq < 0)
|
||||
return -ENXIO;
|
||||
|
||||
spi->irq = irq;
|
||||
|
||||
init_completion(&spi->done);
|
||||
|
||||
spi->clk = devm_clk_get_prepared(dev, NULL);
|
||||
if (IS_ERR(spi->clk)) {
|
||||
dev_err(dev, "could not find clk: %ld\n", PTR_ERR(spi->clk));
|
||||
goto error;
|
||||
}
|
||||
if (IS_ERR(spi->clk))
|
||||
return dev_err_probe(dev, PTR_ERR(spi->clk), "could not find clk\n");
|
||||
|
||||
host->max_speed_hz = min_t(unsigned long, A3700_SPI_MAX_SPEED_HZ,
|
||||
clk_get_rate(spi->clk));
|
||||
|
|
@ -878,23 +869,16 @@ static int a3700_spi_probe(struct platform_device *pdev)
|
|||
|
||||
ret = devm_request_irq(dev, spi->irq, a3700_spi_interrupt, 0,
|
||||
dev_name(dev), host);
|
||||
if (ret) {
|
||||
dev_err(dev, "could not request IRQ: %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "could not request IRQ\n");
|
||||
|
||||
ret = devm_spi_register_controller(dev, host);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to register host\n");
|
||||
goto error;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
spi_controller_put(host);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver a3700_spi_driver = {
|
||||
|
|
|
|||
|
|
@ -697,7 +697,7 @@ static int aspeed_spi_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
|||
{
|
||||
struct aspeed_spi *aspi = spi_controller_get_devdata(desc->mem->spi->controller);
|
||||
struct aspeed_spi_chip *chip = &aspi->chips[spi_get_chipselect(desc->mem->spi, 0)];
|
||||
struct spi_mem_op *op = &desc->info.op_tmpl;
|
||||
struct spi_mem_op *op = desc->info.op_tmpl;
|
||||
u32 ctl_val;
|
||||
int ret = 0;
|
||||
|
||||
|
|
@ -769,7 +769,7 @@ static ssize_t aspeed_spi_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
|||
if (chip->ahb_window_size < offset + len || chip->force_user_mode) {
|
||||
int ret;
|
||||
|
||||
ret = aspeed_spi_read_user(chip, &desc->info.op_tmpl, offset, len, buf);
|
||||
ret = aspeed_spi_read_user(chip, desc->info.op_tmpl, offset, len, buf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else {
|
||||
|
|
@ -891,7 +891,7 @@ static int aspeed_spi_user_unprepare_msg(struct spi_controller *ctlr,
|
|||
static void aspeed_spi_user_transfer_tx(struct aspeed_spi *aspi,
|
||||
struct spi_device *spi,
|
||||
const u8 *tx_buf, u8 *rx_buf,
|
||||
void *dst, u32 len)
|
||||
void __iomem *dst, u32 len)
|
||||
{
|
||||
const struct aspeed_spi_data *data = aspi->data;
|
||||
bool full_duplex_transfer = data->full_duplex && tx_buf == rx_buf;
|
||||
|
|
@ -936,7 +936,7 @@ static int aspeed_spi_user_transfer(struct spi_controller *ctlr,
|
|||
aspeed_spi_set_io_mode(chip, CTRL_IO_QUAD_DATA);
|
||||
|
||||
aspeed_spi_user_transfer_tx(aspi, spi, tx_buf, rx_buf,
|
||||
(void *)ahb_base, xfer->len);
|
||||
ahb_base, xfer->len);
|
||||
}
|
||||
|
||||
if (rx_buf && rx_buf != tx_buf) {
|
||||
|
|
@ -1467,8 +1467,7 @@ static int aspeed_spi_do_calibration(struct aspeed_spi_chip *chip)
|
|||
* must contains the highest number of consecutive "pass"
|
||||
* results and not span across multiple rows.
|
||||
*/
|
||||
static u32 aspeed_spi_ast2600_optimized_timing(u32 rows, u32 cols,
|
||||
u8 buf[rows][cols])
|
||||
static u32 aspeed_spi_ast2600_optimized_timing(u32 rows, u32 cols, u8 *buf)
|
||||
{
|
||||
int r = 0, c = 0;
|
||||
int max = 0;
|
||||
|
|
@ -1478,7 +1477,7 @@ static u32 aspeed_spi_ast2600_optimized_timing(u32 rows, u32 cols,
|
|||
for (j = 0; j < cols;) {
|
||||
int k = j;
|
||||
|
||||
while (k < cols && buf[i][k])
|
||||
while (k < cols && buf[(i * cols) + k])
|
||||
k++;
|
||||
|
||||
if (k - j > max) {
|
||||
|
|
@ -1541,7 +1540,7 @@ static int aspeed_spi_ast2600_calibrate(struct aspeed_spi_chip *chip, u32 hdiv,
|
|||
}
|
||||
}
|
||||
|
||||
calib_point = aspeed_spi_ast2600_optimized_timing(6, 17, calib_res);
|
||||
calib_point = aspeed_spi_ast2600_optimized_timing(6, 17, &calib_res[0][0]);
|
||||
/* No good setting for this frequency */
|
||||
if (calib_point == 0)
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
|
|
@ -496,14 +495,13 @@ static int at91_usart_spi_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
|
||||
ret = -ENOMEM;
|
||||
controller = spi_alloc_host(&pdev->dev, sizeof(*aus));
|
||||
controller = devm_spi_alloc_host(&pdev->dev, sizeof(*aus));
|
||||
if (!controller)
|
||||
goto at91_usart_spi_probe_fail;
|
||||
return -ENOMEM;
|
||||
|
||||
ret = at91_usart_gpio_setup(pdev);
|
||||
if (ret)
|
||||
goto at91_usart_spi_probe_fail;
|
||||
return ret;
|
||||
|
||||
controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP | SPI_CS_HIGH;
|
||||
controller->dev.of_node = pdev->dev.parent->of_node;
|
||||
|
|
@ -525,10 +523,8 @@ static int at91_usart_spi_probe(struct platform_device *pdev)
|
|||
|
||||
aus->dev = &pdev->dev;
|
||||
aus->regs = devm_ioremap_resource(&pdev->dev, regs);
|
||||
if (IS_ERR(aus->regs)) {
|
||||
ret = PTR_ERR(aus->regs);
|
||||
goto at91_usart_spi_probe_fail;
|
||||
}
|
||||
if (IS_ERR(aus->regs))
|
||||
return PTR_ERR(aus->regs);
|
||||
|
||||
aus->irq = irq;
|
||||
aus->clk = clk;
|
||||
|
|
@ -536,11 +532,11 @@ static int at91_usart_spi_probe(struct platform_device *pdev)
|
|||
ret = devm_request_irq(&pdev->dev, irq, at91_usart_spi_interrupt, 0,
|
||||
dev_name(&pdev->dev), controller);
|
||||
if (ret)
|
||||
goto at91_usart_spi_probe_fail;
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(clk);
|
||||
if (ret)
|
||||
goto at91_usart_spi_probe_fail;
|
||||
return ret;
|
||||
|
||||
aus->spi_clk = clk_get_rate(clk);
|
||||
at91_usart_spi_init(aus);
|
||||
|
|
@ -571,43 +567,22 @@ static int at91_usart_spi_probe(struct platform_device *pdev)
|
|||
at91_usart_spi_release_dma(controller);
|
||||
at91_usart_fail_dma:
|
||||
clk_disable_unprepare(clk);
|
||||
at91_usart_spi_probe_fail:
|
||||
spi_controller_put(controller);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
__maybe_unused static int at91_usart_spi_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_controller *ctlr = dev_get_drvdata(dev);
|
||||
struct at91_usart_spi *aus = spi_controller_get_devdata(ctlr);
|
||||
|
||||
clk_disable_unprepare(aus->clk);
|
||||
pinctrl_pm_select_sleep_state(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__maybe_unused static int at91_usart_spi_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct spi_controller *ctrl = dev_get_drvdata(dev);
|
||||
struct at91_usart_spi *aus = spi_controller_get_devdata(ctrl);
|
||||
|
||||
pinctrl_pm_select_default_state(dev);
|
||||
|
||||
return clk_prepare_enable(aus->clk);
|
||||
}
|
||||
|
||||
__maybe_unused static int at91_usart_spi_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_controller *ctrl = dev_get_drvdata(dev);
|
||||
struct at91_usart_spi *aus = spi_controller_get_devdata(ctrl);
|
||||
int ret;
|
||||
|
||||
ret = spi_controller_suspend(ctrl);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!pm_runtime_suspended(dev))
|
||||
at91_usart_spi_runtime_suspend(dev);
|
||||
clk_disable_unprepare(aus->clk);
|
||||
pinctrl_pm_select_sleep_state(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -618,11 +593,11 @@ __maybe_unused static int at91_usart_spi_resume(struct device *dev)
|
|||
struct at91_usart_spi *aus = spi_controller_get_devdata(ctrl);
|
||||
int ret;
|
||||
|
||||
if (!pm_runtime_suspended(dev)) {
|
||||
ret = at91_usart_spi_runtime_resume(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
pinctrl_pm_select_default_state(dev);
|
||||
|
||||
ret = clk_prepare_enable(aus->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
at91_usart_spi_init(aus);
|
||||
|
||||
|
|
@ -634,20 +609,14 @@ static void at91_usart_spi_remove(struct platform_device *pdev)
|
|||
struct spi_controller *ctlr = platform_get_drvdata(pdev);
|
||||
struct at91_usart_spi *aus = spi_controller_get_devdata(ctlr);
|
||||
|
||||
spi_controller_get(ctlr);
|
||||
|
||||
spi_unregister_controller(ctlr);
|
||||
|
||||
at91_usart_spi_release_dma(ctlr);
|
||||
clk_disable_unprepare(aus->clk);
|
||||
|
||||
spi_controller_put(ctlr);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops at91_usart_spi_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(at91_usart_spi_suspend, at91_usart_spi_resume)
|
||||
SET_RUNTIME_PM_OPS(at91_usart_spi_runtime_suspend,
|
||||
at91_usart_spi_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static struct platform_driver at91_usart_spi_driver = {
|
||||
|
|
|
|||
|
|
@ -550,7 +550,7 @@ static int atcspi_probe(struct platform_device *pdev)
|
|||
struct resource *mem_res;
|
||||
int ret;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*spi));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*spi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -559,28 +559,24 @@ static int atcspi_probe(struct platform_device *pdev)
|
|||
spi->dev = &pdev->dev;
|
||||
dev_set_drvdata(&pdev->dev, host);
|
||||
|
||||
mutex_init(&spi->mutex_lock);
|
||||
ret = devm_mutex_init(&pdev->dev, &spi->mutex_lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = atcspi_init_resources(pdev, spi, &mem_res);
|
||||
if (ret)
|
||||
goto free_controller;
|
||||
return ret;
|
||||
|
||||
ret = atcspi_enable_clk(spi);
|
||||
if (ret)
|
||||
goto free_controller;
|
||||
return ret;
|
||||
|
||||
atcspi_init_controller(pdev, spi, host, mem_res);
|
||||
|
||||
ret = atcspi_setup(spi);
|
||||
if (ret)
|
||||
goto free_controller;
|
||||
return ret;
|
||||
|
||||
ret = devm_spi_register_controller(&pdev->dev, host);
|
||||
if (ret) {
|
||||
dev_err_probe(spi->dev, ret,
|
||||
"Failed to register SPI controller\n");
|
||||
goto free_controller;
|
||||
}
|
||||
spi->use_dma = false;
|
||||
if (ATCSPI_DMA_SUPPORT) {
|
||||
ret = atcspi_configure_dma(spi);
|
||||
|
|
@ -591,12 +587,12 @@ static int atcspi_probe(struct platform_device *pdev)
|
|||
spi->use_dma = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
ret = devm_spi_register_controller(&pdev->dev, host);
|
||||
if (ret)
|
||||
return dev_err_probe(spi->dev, ret,
|
||||
"Failed to register SPI controller\n");
|
||||
|
||||
free_controller:
|
||||
mutex_destroy(&spi->mutex_lock);
|
||||
spi_controller_put(host);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int atcspi_suspend(struct device *dev)
|
||||
|
|
|
|||
|
|
@ -559,6 +559,38 @@ static int atmel_spi_dma_slave_config(struct atmel_spi *as, u8 bits_per_word)
|
|||
return err;
|
||||
}
|
||||
|
||||
static void atmel_spi_release_dma(void *data)
|
||||
{
|
||||
struct spi_controller *host = data;
|
||||
struct atmel_spi *as = spi_controller_get_devdata(host);
|
||||
struct device *dev = &as->pdev->dev;
|
||||
|
||||
if (host->dma_tx) {
|
||||
dma_release_channel(host->dma_tx);
|
||||
host->dma_tx = NULL;
|
||||
}
|
||||
|
||||
if (host->dma_rx) {
|
||||
dma_release_channel(host->dma_rx);
|
||||
host->dma_rx = NULL;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
|
||||
if (as->addr_tx_bbuf) {
|
||||
dma_free_coherent(dev, SPI_MAX_DMA_XFER,
|
||||
as->addr_tx_bbuf,
|
||||
as->dma_addr_tx_bbuf);
|
||||
as->addr_tx_bbuf = NULL;
|
||||
}
|
||||
if (as->addr_rx_bbuf) {
|
||||
dma_free_coherent(dev, SPI_MAX_DMA_XFER,
|
||||
as->addr_rx_bbuf,
|
||||
as->dma_addr_rx_bbuf);
|
||||
as->addr_rx_bbuf = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int atmel_spi_configure_dma(struct spi_controller *host,
|
||||
struct atmel_spi *as)
|
||||
{
|
||||
|
|
@ -569,7 +601,8 @@ static int atmel_spi_configure_dma(struct spi_controller *host,
|
|||
if (IS_ERR(host->dma_tx)) {
|
||||
err = PTR_ERR(host->dma_tx);
|
||||
dev_dbg(dev, "No TX DMA channel, DMA is disabled\n");
|
||||
goto error_clear;
|
||||
host->dma_tx = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
host->dma_rx = dma_request_chan(dev, "rx");
|
||||
|
|
@ -580,26 +613,45 @@ static int atmel_spi_configure_dma(struct spi_controller *host,
|
|||
* requested tx channel.
|
||||
*/
|
||||
dev_dbg(dev, "No RX DMA channel, DMA is disabled\n");
|
||||
goto error;
|
||||
host->dma_rx = NULL;
|
||||
goto err_release_dma;
|
||||
}
|
||||
|
||||
err = atmel_spi_dma_slave_config(as, 8);
|
||||
if (err)
|
||||
goto error;
|
||||
goto err_release_dma;
|
||||
|
||||
if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
|
||||
as->addr_tx_bbuf = dma_alloc_coherent(dev, SPI_MAX_DMA_XFER,
|
||||
&as->dma_addr_tx_bbuf,
|
||||
GFP_KERNEL | GFP_DMA);
|
||||
if (!as->addr_tx_bbuf) {
|
||||
err = -ENOMEM;
|
||||
goto err_release_dma;
|
||||
}
|
||||
|
||||
as->addr_rx_bbuf = dma_alloc_coherent(dev, SPI_MAX_DMA_XFER,
|
||||
&as->dma_addr_rx_bbuf,
|
||||
GFP_KERNEL | GFP_DMA);
|
||||
if (!as->addr_rx_bbuf) {
|
||||
err = -ENOMEM;
|
||||
goto err_release_dma;
|
||||
}
|
||||
}
|
||||
|
||||
err = devm_add_action_or_reset(dev, atmel_spi_release_dma, host);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dev_info(&as->pdev->dev,
|
||||
"Using %s (tx) and %s (rx) for DMA transfers\n",
|
||||
dma_chan_name(host->dma_tx),
|
||||
dma_chan_name(host->dma_rx));
|
||||
"Using %s (tx) and %s (rx) for DMA transfers\n",
|
||||
dma_chan_name(host->dma_tx), dma_chan_name(host->dma_rx));
|
||||
|
||||
return 0;
|
||||
error:
|
||||
if (!IS_ERR(host->dma_rx))
|
||||
dma_release_channel(host->dma_rx);
|
||||
if (!IS_ERR(host->dma_tx))
|
||||
dma_release_channel(host->dma_tx);
|
||||
error_clear:
|
||||
host->dma_tx = host->dma_rx = NULL;
|
||||
|
||||
err_release_dma:
|
||||
atmel_spi_release_dma(host);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -611,18 +663,6 @@ static void atmel_spi_stop_dma(struct spi_controller *host)
|
|||
dmaengine_terminate_all(host->dma_tx);
|
||||
}
|
||||
|
||||
static void atmel_spi_release_dma(struct spi_controller *host)
|
||||
{
|
||||
if (host->dma_rx) {
|
||||
dma_release_channel(host->dma_rx);
|
||||
host->dma_rx = NULL;
|
||||
}
|
||||
if (host->dma_tx) {
|
||||
dma_release_channel(host->dma_tx);
|
||||
host->dma_tx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is called by the DMA driver from tasklet context */
|
||||
static void dma_callback(void *data)
|
||||
{
|
||||
|
|
@ -1528,7 +1568,7 @@ static int atmel_spi_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(clk);
|
||||
|
||||
/* setup spi core then atmel-specific driver state */
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*as));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*as));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -1555,18 +1595,15 @@ static int atmel_spi_probe(struct platform_device *pdev)
|
|||
|
||||
as->pdev = pdev;
|
||||
as->regs = devm_platform_get_and_ioremap_resource(pdev, 0, ®s);
|
||||
if (IS_ERR(as->regs)) {
|
||||
ret = PTR_ERR(as->regs);
|
||||
goto out_unmap_regs;
|
||||
}
|
||||
if (IS_ERR(as->regs))
|
||||
return PTR_ERR(as->regs);
|
||||
|
||||
as->phybase = regs->start;
|
||||
as->irq = irq;
|
||||
as->clk = clk;
|
||||
as->gclk = devm_clk_get_optional(&pdev->dev, "spi_gclk");
|
||||
if (IS_ERR(as->gclk)) {
|
||||
ret = PTR_ERR(as->gclk);
|
||||
goto out_unmap_regs;
|
||||
}
|
||||
if (IS_ERR(as->gclk))
|
||||
return PTR_ERR(as->gclk);
|
||||
|
||||
init_completion(&as->xfer_completion);
|
||||
|
||||
|
|
@ -1576,39 +1613,14 @@ static int atmel_spi_probe(struct platform_device *pdev)
|
|||
as->use_pdc = false;
|
||||
if (as->caps.has_dma_support) {
|
||||
ret = atmel_spi_configure_dma(host, as);
|
||||
if (ret == 0) {
|
||||
if (ret == 0)
|
||||
as->use_dma = true;
|
||||
} else if (ret == -EPROBE_DEFER) {
|
||||
goto out_unmap_regs;
|
||||
}
|
||||
else if (ret == -EPROBE_DEFER)
|
||||
return ret;
|
||||
} else if (as->caps.has_pdc_support) {
|
||||
as->use_pdc = true;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
|
||||
as->addr_rx_bbuf = dma_alloc_coherent(&pdev->dev,
|
||||
SPI_MAX_DMA_XFER,
|
||||
&as->dma_addr_rx_bbuf,
|
||||
GFP_KERNEL | GFP_DMA);
|
||||
if (!as->addr_rx_bbuf) {
|
||||
as->use_dma = false;
|
||||
} else {
|
||||
as->addr_tx_bbuf = dma_alloc_coherent(&pdev->dev,
|
||||
SPI_MAX_DMA_XFER,
|
||||
&as->dma_addr_tx_bbuf,
|
||||
GFP_KERNEL | GFP_DMA);
|
||||
if (!as->addr_tx_bbuf) {
|
||||
as->use_dma = false;
|
||||
dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
|
||||
as->addr_rx_bbuf,
|
||||
as->dma_addr_rx_bbuf);
|
||||
}
|
||||
}
|
||||
if (!as->use_dma)
|
||||
dev_info(host->dev.parent,
|
||||
" can not allocate dma coherent memory\n");
|
||||
}
|
||||
|
||||
if (as->caps.has_dma_support && !as->use_dma)
|
||||
dev_info(&pdev->dev, "Atmel SPI Controller using PIO only\n");
|
||||
|
||||
|
|
@ -1620,12 +1632,12 @@ static int atmel_spi_probe(struct platform_device *pdev)
|
|||
0, dev_name(&pdev->dev), host);
|
||||
}
|
||||
if (ret)
|
||||
goto out_unmap_regs;
|
||||
return ret;
|
||||
|
||||
/* Initialize the hardware */
|
||||
ret = clk_prepare_enable(clk);
|
||||
if (ret)
|
||||
goto out_free_irq;
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* In cases where the peripheral clock is higher,the FLEX_SPI_CSRx.SCBR
|
||||
|
|
@ -1668,18 +1680,13 @@ static int atmel_spi_probe(struct platform_device *pdev)
|
|||
out_free_dma:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
|
||||
if (as->use_dma)
|
||||
atmel_spi_release_dma(host);
|
||||
|
||||
spi_writel(as, CR, SPI_BIT(SWRST));
|
||||
spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
|
||||
clk_disable_unprepare(as->gclk);
|
||||
if (as->gclk)
|
||||
clk_disable_unprepare(as->gclk);
|
||||
out_disable_clk:
|
||||
clk_disable_unprepare(clk);
|
||||
out_free_irq:
|
||||
out_unmap_regs:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1688,25 +1695,13 @@ static void atmel_spi_remove(struct platform_device *pdev)
|
|||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct atmel_spi *as = spi_controller_get_devdata(host);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
/* reset the hardware and block queue progress */
|
||||
if (as->use_dma) {
|
||||
if (as->use_dma)
|
||||
atmel_spi_stop_dma(host);
|
||||
atmel_spi_release_dma(host);
|
||||
if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
|
||||
dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
|
||||
as->addr_tx_bbuf,
|
||||
as->dma_addr_tx_bbuf);
|
||||
dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
|
||||
as->addr_rx_bbuf,
|
||||
as->dma_addr_rx_bbuf);
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irq(&as->lock);
|
||||
spi_writel(as, CR, SPI_BIT(SWRST));
|
||||
|
|
@ -1720,8 +1715,6 @@ static void atmel_spi_remove(struct platform_device *pdev)
|
|||
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
static int atmel_spi_runtime_suspend(struct device *dev)
|
||||
|
|
|
|||
|
|
@ -783,7 +783,7 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
|
|||
"failed get pll clk rate\n");
|
||||
}
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*bs));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*bs));
|
||||
if (!host)
|
||||
return dev_err_probe(dev, -ENOMEM, "alloc host no mem\n");
|
||||
|
||||
|
|
@ -796,10 +796,8 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
|
|||
bs->fifo = (u8 __iomem *)(bs->regs + HSSPI_FIFO_REG(0));
|
||||
bs->wait_mode = HSSPI_WAIT_MODE_POLLING;
|
||||
bs->prepend_buf = devm_kzalloc(dev, HSSPI_BUFFER_LEN, GFP_KERNEL);
|
||||
if (!bs->prepend_buf) {
|
||||
ret = -ENOMEM;
|
||||
goto out_put_host;
|
||||
}
|
||||
if (!bs->prepend_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&bs->bus_mutex);
|
||||
mutex_init(&bs->msg_mutex);
|
||||
|
|
@ -845,7 +843,7 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
|
|||
pdev->name, bs);
|
||||
|
||||
if (ret)
|
||||
goto out_put_host;
|
||||
return ret;
|
||||
}
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
|
@ -869,8 +867,7 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
|
|||
sysfs_remove_group(&pdev->dev.kobj, &bcm63xx_hsspi_group);
|
||||
out_pm_disable:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
out_put_host:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -880,15 +877,11 @@ static void bcm63xx_hsspi_remove(struct platform_device *pdev)
|
|||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct bcm63xx_hsspi *bs = spi_controller_get_devdata(host);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
/* reset the hardware and block queue progress */
|
||||
__raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
|
||||
sysfs_remove_group(&pdev->dev.kobj, &bcm63xx_hsspi_group);
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
|
|||
|
|
@ -477,8 +477,7 @@ static const struct platform_device_id bcm63xx_spi_dev_match[] = {
|
|||
.name = "bcm6358-spi",
|
||||
.driver_data = (unsigned long)bcm6358_spi_reg_offsets,
|
||||
},
|
||||
{
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, bcm63xx_spi_dev_match);
|
||||
|
||||
|
|
@ -541,11 +540,9 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(reset))
|
||||
return PTR_ERR(reset);
|
||||
|
||||
host = spi_alloc_host(dev, sizeof(*bs));
|
||||
if (!host) {
|
||||
dev_err(dev, "out of memory\n");
|
||||
host = devm_spi_alloc_host(dev, sizeof(*bs));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bs = spi_controller_get_devdata(host);
|
||||
init_completion(&bs->done);
|
||||
|
|
@ -554,10 +551,8 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
|
|||
bs->pdev = pdev;
|
||||
|
||||
bs->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &r);
|
||||
if (IS_ERR(bs->regs)) {
|
||||
ret = PTR_ERR(bs->regs);
|
||||
goto out_err;
|
||||
}
|
||||
if (IS_ERR(bs->regs))
|
||||
return PTR_ERR(bs->regs);
|
||||
|
||||
bs->irq = irq;
|
||||
bs->clk = clk;
|
||||
|
|
@ -568,7 +563,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
|
|||
pdev->name, host);
|
||||
if (ret) {
|
||||
dev_err(dev, "unable to request irq\n");
|
||||
goto out_err;
|
||||
return ret;
|
||||
}
|
||||
|
||||
host->bus_num = bus_num;
|
||||
|
|
@ -587,7 +582,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
|
|||
/* Initialize hardware */
|
||||
ret = clk_prepare_enable(bs->clk);
|
||||
if (ret)
|
||||
goto out_err;
|
||||
return ret;
|
||||
|
||||
ret = reset_control_reset(reset);
|
||||
if (ret) {
|
||||
|
|
@ -615,8 +610,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
|
|||
|
||||
out_clk_disable:
|
||||
clk_disable_unprepare(clk);
|
||||
out_err:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -625,8 +619,6 @@ static void bcm63xx_spi_remove(struct platform_device *pdev)
|
|||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct bcm63xx_spi *bs = spi_controller_get_devdata(host);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
/* reset spi block */
|
||||
|
|
@ -634,8 +626,6 @@ static void bcm63xx_spi_remove(struct platform_device *pdev)
|
|||
|
||||
/* HW shutdown */
|
||||
clk_disable_unprepare(bs->clk);
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
static int bcm63xx_spi_suspend(struct device *dev)
|
||||
|
|
|
|||
|
|
@ -420,11 +420,6 @@ EXPORT_SYMBOL_GPL(spi_bitbang_init);
|
|||
* This routine registers the spi_controller, which will process requests in a
|
||||
* dedicated task, keeping IRQs unblocked most of the time. To stop
|
||||
* processing those requests, call spi_bitbang_stop().
|
||||
*
|
||||
* On success, this routine will take a reference to the controller. The caller
|
||||
* is responsible for calling spi_bitbang_stop() to decrement the reference and
|
||||
* spi_controller_put() as counterpart of spi_alloc_host() to prevent a memory
|
||||
* leak.
|
||||
*/
|
||||
int spi_bitbang_start(struct spi_bitbang *bitbang)
|
||||
{
|
||||
|
|
@ -438,11 +433,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
|
|||
/* driver may get busy before register() returns, especially
|
||||
* if someone registered boardinfo for devices
|
||||
*/
|
||||
ret = spi_register_controller(spi_controller_get(ctlr));
|
||||
if (ret)
|
||||
spi_controller_put(ctlr);
|
||||
|
||||
return ret;
|
||||
return spi_register_controller(ctlr);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(spi_bitbang_start);
|
||||
|
||||
|
|
|
|||
|
|
@ -1478,7 +1478,6 @@ static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
|||
int ret;
|
||||
struct cqspi_st *cqspi = spi_controller_get_devdata(mem->spi->controller);
|
||||
struct device *dev = &cqspi->pdev->dev;
|
||||
const struct cqspi_driver_platdata *ddata = of_device_get_match_data(dev);
|
||||
|
||||
if (refcount_read(&cqspi->inflight_ops) == 0)
|
||||
return -ENODEV;
|
||||
|
|
@ -1494,18 +1493,15 @@ static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) {
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret) {
|
||||
dev_err(&mem->spi->dev, "resume failed with %d\n", ret);
|
||||
goto dec_inflight_refcount;
|
||||
}
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret) {
|
||||
dev_err(&mem->spi->dev, "resume failed with %d\n", ret);
|
||||
goto dec_inflight_refcount;
|
||||
}
|
||||
|
||||
ret = cqspi_mem_process(mem, op);
|
||||
|
||||
if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM)))
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
if (ret)
|
||||
dev_err(&mem->spi->dev, "operation failed with %d\n", ret);
|
||||
|
|
@ -1957,13 +1953,11 @@ static int cqspi_probe(struct platform_device *pdev)
|
|||
cqspi->current_cs = -1;
|
||||
cqspi->sclk = 0;
|
||||
|
||||
if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) {
|
||||
pm_runtime_set_autosuspend_delay(dev, CQSPI_AUTOSUSPEND_TIMEOUT);
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_get_noresume(dev);
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
}
|
||||
pm_runtime_set_autosuspend_delay(dev, CQSPI_AUTOSUSPEND_TIMEOUT);
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_get_noresume(dev);
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
host->num_chipselect = cqspi->num_chipselect;
|
||||
|
||||
|
|
@ -1993,12 +1987,11 @@ static int cqspi_probe(struct platform_device *pdev)
|
|||
if (cqspi->rx_chan)
|
||||
dma_release_channel(cqspi->rx_chan);
|
||||
disable_rpm:
|
||||
if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) {
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_suspended(dev);
|
||||
pm_runtime_put_noidle(dev);
|
||||
pm_runtime_dont_use_autosuspend(dev);
|
||||
}
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_suspended(dev);
|
||||
pm_runtime_put_noidle(dev);
|
||||
pm_runtime_dont_use_autosuspend(dev);
|
||||
|
||||
cqspi_controller_enable(cqspi, 0);
|
||||
disable_clks:
|
||||
clk_bulk_disable_unprepare(CLK_QSPI_NUM, cqspi->clks);
|
||||
|
|
@ -2008,13 +2001,10 @@ static int cqspi_probe(struct platform_device *pdev)
|
|||
|
||||
static void cqspi_remove(struct platform_device *pdev)
|
||||
{
|
||||
const struct cqspi_driver_platdata *ddata;
|
||||
struct cqspi_st *cqspi = platform_get_drvdata(pdev);
|
||||
struct device *dev = &pdev->dev;
|
||||
const struct cqspi_driver_platdata *ddata = cqspi->ddata;
|
||||
int ret = 0;
|
||||
|
||||
ddata = of_device_get_match_data(dev);
|
||||
|
||||
spi_unregister_controller(cqspi->host);
|
||||
|
||||
refcount_set(&cqspi->refcount, 0);
|
||||
|
|
@ -2033,12 +2023,10 @@ static void cqspi_remove(struct platform_device *pdev)
|
|||
clk_bulk_disable_unprepare(CLK_QSPI_NUM, cqspi->clks);
|
||||
}
|
||||
|
||||
if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) {
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
pm_runtime_dont_use_autosuspend(&pdev->dev);
|
||||
}
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
pm_runtime_dont_use_autosuspend(&pdev->dev);
|
||||
}
|
||||
|
||||
static int cqspi_runtime_suspend(struct device *dev)
|
||||
|
|
|
|||
|
|
@ -369,6 +369,8 @@ struct cdns_xspi_dev {
|
|||
|
||||
void *in_buffer;
|
||||
const void *out_buffer;
|
||||
/* Slave DMA data width in bytes (4 or 8). */
|
||||
u8 dma_data_width;
|
||||
|
||||
u8 hw_num_banks;
|
||||
|
||||
|
|
@ -453,8 +455,7 @@ static bool cdns_mrvl_xspi_setup_clock(struct cdns_xspi_dev *cdns_xspi,
|
|||
writel(clk_reg,
|
||||
cdns_xspi->auxbase + MRVL_XSPI_CLK_CTRL_AUX_REG);
|
||||
clk_reg = FIELD_PREP(MRVL_XSPI_CLK_DIV, i);
|
||||
clk_reg &= ~MRVL_XSPI_CLK_DIV;
|
||||
clk_reg |= FIELD_PREP(MRVL_XSPI_CLK_DIV, i);
|
||||
FIELD_MODIFY(MRVL_XSPI_CLK_DIV, &clk_reg, i);
|
||||
clk_reg |= MRVL_XSPI_CLK_ENABLE;
|
||||
clk_reg |= MRVL_XSPI_IRQ_ENABLE;
|
||||
update_clk = true;
|
||||
|
|
@ -573,11 +574,56 @@ static int cdns_xspi_controller_init(struct cdns_xspi_dev *cdns_xspi)
|
|||
|
||||
ctrl_features = readl(cdns_xspi->iobase + CDNS_XSPI_CTRL_FEATURES_REG);
|
||||
cdns_xspi->hw_num_banks = FIELD_GET(CDNS_XSPI_NUM_BANKS, ctrl_features);
|
||||
cdns_xspi->dma_data_width = (ctrl_features & CDNS_XSPI_DMA_DATA_WIDTH) ? 8 : 4;
|
||||
cdns_xspi->set_interrupts_handler(cdns_xspi, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void cdns_xspi_sdma_read(struct cdns_xspi_dev *cdns_xspi, size_t len)
|
||||
{
|
||||
void __iomem *src = cdns_xspi->sdmabase;
|
||||
void *buf = cdns_xspi->in_buffer;
|
||||
size_t offset = 0;
|
||||
|
||||
if (cdns_xspi->dma_data_width == 4) {
|
||||
if (IS_ALIGNED((uintptr_t)src, 4) && IS_ALIGNED((uintptr_t)buf, 4)) {
|
||||
ioread32_rep(src, buf, len >> 2);
|
||||
offset = len & ~0x3;
|
||||
len -= offset;
|
||||
}
|
||||
} else {
|
||||
if (IS_ALIGNED((uintptr_t)src, 8) && IS_ALIGNED((uintptr_t)buf, 8)) {
|
||||
readsq(src, buf, len >> 3);
|
||||
offset = len & ~0x7;
|
||||
len -= offset;
|
||||
}
|
||||
}
|
||||
ioread8_rep(src, (u8 *)buf + offset, len);
|
||||
}
|
||||
|
||||
static inline void cdns_xspi_sdma_write(struct cdns_xspi_dev *cdns_xspi, size_t len)
|
||||
{
|
||||
void __iomem *dst = cdns_xspi->sdmabase;
|
||||
const void *buf = cdns_xspi->out_buffer;
|
||||
size_t offset = 0;
|
||||
|
||||
if (cdns_xspi->dma_data_width == 4) {
|
||||
if (IS_ALIGNED((uintptr_t)dst, 4) && IS_ALIGNED((uintptr_t)buf, 4)) {
|
||||
iowrite32_rep(dst, buf, len >> 2);
|
||||
offset = len & ~0x3;
|
||||
len -= offset;
|
||||
}
|
||||
} else {
|
||||
if (IS_ALIGNED((uintptr_t)dst, 8) && IS_ALIGNED((uintptr_t)buf, 8)) {
|
||||
writesq(dst, buf, len >> 3);
|
||||
offset = len & ~0x7;
|
||||
len -= offset;
|
||||
}
|
||||
}
|
||||
iowrite8_rep(dst, (const u8 *)buf + offset, len);
|
||||
}
|
||||
|
||||
static void cdns_xspi_sdma_handle(struct cdns_xspi_dev *cdns_xspi)
|
||||
{
|
||||
u32 sdma_size, sdma_trd_info;
|
||||
|
|
@ -589,13 +635,11 @@ static void cdns_xspi_sdma_handle(struct cdns_xspi_dev *cdns_xspi)
|
|||
|
||||
switch (sdma_dir) {
|
||||
case CDNS_XSPI_SDMA_DIR_READ:
|
||||
ioread8_rep(cdns_xspi->sdmabase,
|
||||
cdns_xspi->in_buffer, sdma_size);
|
||||
cdns_xspi_sdma_read(cdns_xspi, sdma_size);
|
||||
break;
|
||||
|
||||
case CDNS_XSPI_SDMA_DIR_WRITE:
|
||||
iowrite8_rep(cdns_xspi->sdmabase,
|
||||
cdns_xspi->out_buffer, sdma_size);
|
||||
cdns_xspi_sdma_write(cdns_xspi, sdma_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -635,7 +635,7 @@ static int cdns_target_abort(struct spi_controller *ctlr)
|
|||
*/
|
||||
static int cdns_spi_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0, irq;
|
||||
int ret, irq;
|
||||
struct spi_controller *ctlr;
|
||||
struct cdns_spi *xspi;
|
||||
u32 num_cs;
|
||||
|
|
@ -643,9 +643,9 @@ static int cdns_spi_probe(struct platform_device *pdev)
|
|||
|
||||
target = of_property_read_bool(pdev->dev.of_node, "spi-slave");
|
||||
if (target)
|
||||
ctlr = spi_alloc_target(&pdev->dev, sizeof(*xspi));
|
||||
ctlr = devm_spi_alloc_target(&pdev->dev, sizeof(*xspi));
|
||||
else
|
||||
ctlr = spi_alloc_host(&pdev->dev, sizeof(*xspi));
|
||||
ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*xspi));
|
||||
|
||||
if (!ctlr)
|
||||
return -ENOMEM;
|
||||
|
|
@ -654,23 +654,19 @@ static int cdns_spi_probe(struct platform_device *pdev)
|
|||
platform_set_drvdata(pdev, ctlr);
|
||||
|
||||
xspi->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(xspi->regs)) {
|
||||
ret = PTR_ERR(xspi->regs);
|
||||
goto remove_ctlr;
|
||||
}
|
||||
if (IS_ERR(xspi->regs))
|
||||
return PTR_ERR(xspi->regs);
|
||||
|
||||
xspi->pclk = devm_clk_get_enabled(&pdev->dev, "pclk");
|
||||
if (IS_ERR(xspi->pclk)) {
|
||||
dev_err(&pdev->dev, "pclk clock not found.\n");
|
||||
ret = PTR_ERR(xspi->pclk);
|
||||
goto remove_ctlr;
|
||||
return PTR_ERR(xspi->pclk);
|
||||
}
|
||||
|
||||
xspi->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, "spi");
|
||||
if (IS_ERR(xspi->rstc)) {
|
||||
ret = dev_err_probe(&pdev->dev, PTR_ERR(xspi->rstc),
|
||||
"Cannot get SPI reset.\n");
|
||||
goto remove_ctlr;
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(xspi->rstc),
|
||||
"Cannot get SPI reset.\n");
|
||||
}
|
||||
|
||||
reset_control_assert(xspi->rstc);
|
||||
|
|
@ -679,8 +675,7 @@ static int cdns_spi_probe(struct platform_device *pdev)
|
|||
xspi->ref_clk = devm_clk_get_enabled(&pdev->dev, "ref_clk");
|
||||
if (IS_ERR(xspi->ref_clk)) {
|
||||
dev_err(&pdev->dev, "ref_clk clock not found.\n");
|
||||
ret = PTR_ERR(xspi->ref_clk);
|
||||
goto remove_ctlr;
|
||||
return PTR_ERR(xspi->ref_clk);
|
||||
}
|
||||
|
||||
if (!spi_controller_is_target(ctlr)) {
|
||||
|
|
@ -710,7 +705,7 @@ static int cdns_spi_probe(struct platform_device *pdev)
|
|||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
ret = irq;
|
||||
goto clk_dis_all;
|
||||
goto err_disable_rpm;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, irq, cdns_spi_irq,
|
||||
|
|
@ -718,7 +713,7 @@ static int cdns_spi_probe(struct platform_device *pdev)
|
|||
if (ret != 0) {
|
||||
ret = -ENXIO;
|
||||
dev_err(&pdev->dev, "request_irq failed\n");
|
||||
goto clk_dis_all;
|
||||
goto err_disable_rpm;
|
||||
}
|
||||
|
||||
ctlr->use_gpio_descriptors = true;
|
||||
|
|
@ -748,23 +743,22 @@ static int cdns_spi_probe(struct platform_device *pdev)
|
|||
ret = spi_register_controller(ctlr);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "spi_register_controller failed\n");
|
||||
goto clk_dis_all;
|
||||
goto err_disable_rpm;
|
||||
}
|
||||
|
||||
if (!spi_controller_is_target(ctlr))
|
||||
pm_runtime_put_autosuspend(&pdev->dev);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
|
||||
clk_dis_all:
|
||||
err_disable_rpm:
|
||||
if (!spi_controller_is_target(ctlr)) {
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
pm_runtime_dont_use_autosuspend(&pdev->dev);
|
||||
}
|
||||
remove_ctlr:
|
||||
spi_controller_put(ctlr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -785,8 +779,6 @@ static void cdns_spi_remove(struct platform_device *pdev)
|
|||
if (!spi_controller_is_target(ctlr))
|
||||
ret = pm_runtime_get_sync(&pdev->dev);
|
||||
|
||||
spi_controller_get(ctlr);
|
||||
|
||||
spi_unregister_controller(ctlr);
|
||||
|
||||
if (ret >= 0)
|
||||
|
|
@ -798,8 +790,6 @@ static void cdns_spi_remove(struct platform_device *pdev)
|
|||
pm_runtime_put_noidle(&pdev->dev);
|
||||
pm_runtime_dont_use_autosuspend(&pdev->dev);
|
||||
}
|
||||
|
||||
spi_controller_put(ctlr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -23,17 +23,15 @@ static int octeon_spi_probe(struct platform_device *pdev)
|
|||
struct octeon_spi *p;
|
||||
int err = -ENOENT;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(struct octeon_spi));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(struct octeon_spi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
p = spi_controller_get_devdata(host);
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
||||
reg_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(reg_base)) {
|
||||
err = PTR_ERR(reg_base);
|
||||
goto fail;
|
||||
}
|
||||
if (IS_ERR(reg_base))
|
||||
return PTR_ERR(reg_base);
|
||||
|
||||
p->register_base = reg_base;
|
||||
p->sys_freq = octeon_get_io_clock_rate();
|
||||
|
|
@ -57,15 +55,12 @@ static int octeon_spi_probe(struct platform_device *pdev)
|
|||
err = spi_register_controller(host);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "register host failed: %d\n", err);
|
||||
goto fail;
|
||||
return err;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "OCTEON SPI bus driver\n");
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
spi_controller_put(host);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void octeon_spi_remove(struct platform_device *pdev)
|
||||
|
|
@ -73,14 +68,10 @@ static void octeon_spi_remove(struct platform_device *pdev)
|
|||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct octeon_spi *p = spi_controller_get_devdata(host);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
/* Clear the CSENA* and put everything in a known state. */
|
||||
writeq(0, p->register_base + OCTEON_SPI_CFG(p));
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
static const struct of_device_id octeon_spi_match[] = {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ static int thunderx_spi_probe(struct pci_dev *pdev,
|
|||
struct octeon_spi *p;
|
||||
int ret;
|
||||
|
||||
host = spi_alloc_host(dev, sizeof(struct octeon_spi));
|
||||
host = devm_spi_alloc_host(dev, sizeof(struct octeon_spi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -32,17 +32,15 @@ static int thunderx_spi_probe(struct pci_dev *pdev,
|
|||
|
||||
ret = pcim_enable_device(pdev);
|
||||
if (ret)
|
||||
goto error;
|
||||
return ret;
|
||||
|
||||
ret = pcim_request_all_regions(pdev, DRV_NAME);
|
||||
if (ret)
|
||||
goto error;
|
||||
return ret;
|
||||
|
||||
p->register_base = pcim_iomap(pdev, 0, pci_resource_len(pdev, 0));
|
||||
if (!p->register_base) {
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
if (!p->register_base)
|
||||
return -EINVAL;
|
||||
|
||||
p->regs.config = 0x1000;
|
||||
p->regs.status = 0x1008;
|
||||
|
|
@ -50,10 +48,8 @@ static int thunderx_spi_probe(struct pci_dev *pdev,
|
|||
p->regs.data = 0x1080;
|
||||
|
||||
p->clk = devm_clk_get_enabled(dev, NULL);
|
||||
if (IS_ERR(p->clk)) {
|
||||
ret = PTR_ERR(p->clk);
|
||||
goto error;
|
||||
}
|
||||
if (IS_ERR(p->clk))
|
||||
return PTR_ERR(p->clk);
|
||||
|
||||
p->sys_freq = clk_get_rate(p->clk);
|
||||
if (!p->sys_freq)
|
||||
|
|
@ -70,15 +66,7 @@ static int thunderx_spi_probe(struct pci_dev *pdev,
|
|||
|
||||
pci_set_drvdata(pdev, host);
|
||||
|
||||
ret = spi_register_controller(host);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
spi_controller_put(host);
|
||||
return ret;
|
||||
return spi_register_controller(host);
|
||||
}
|
||||
|
||||
static void thunderx_spi_remove(struct pci_dev *pdev)
|
||||
|
|
@ -90,14 +78,10 @@ static void thunderx_spi_remove(struct pci_dev *pdev)
|
|||
if (!p)
|
||||
return;
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
/* Put everything in a known state. */
|
||||
writeq(0, p->register_base + OCTEON_SPI_CFG(p));
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
static const struct pci_device_id thunderx_spi_pci_id_table[] = {
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ static int spi_clps711x_probe(struct platform_device *pdev)
|
|||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*hw));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*hw));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -113,22 +113,16 @@ static int spi_clps711x_probe(struct platform_device *pdev)
|
|||
hw = spi_controller_get_devdata(host);
|
||||
|
||||
hw->spi_clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(hw->spi_clk)) {
|
||||
ret = PTR_ERR(hw->spi_clk);
|
||||
goto err_out;
|
||||
}
|
||||
if (IS_ERR(hw->spi_clk))
|
||||
return PTR_ERR(hw->spi_clk);
|
||||
|
||||
hw->syscon = syscon_regmap_lookup_by_phandle(np, "syscon");
|
||||
if (IS_ERR(hw->syscon)) {
|
||||
ret = PTR_ERR(hw->syscon);
|
||||
goto err_out;
|
||||
}
|
||||
if (IS_ERR(hw->syscon))
|
||||
return PTR_ERR(hw->syscon);
|
||||
|
||||
hw->syncio = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(hw->syncio)) {
|
||||
ret = PTR_ERR(hw->syncio);
|
||||
goto err_out;
|
||||
}
|
||||
if (IS_ERR(hw->syncio))
|
||||
return PTR_ERR(hw->syncio);
|
||||
|
||||
/* Disable extended mode due hardware problems */
|
||||
regmap_update_bits(hw->syscon, SYSCON_OFFSET, SYSCON3_ADCCON, 0);
|
||||
|
|
@ -139,16 +133,9 @@ static int spi_clps711x_probe(struct platform_device *pdev)
|
|||
ret = devm_request_irq(&pdev->dev, irq, spi_clps711x_isr, 0,
|
||||
dev_name(&pdev->dev), host);
|
||||
if (ret)
|
||||
goto err_out;
|
||||
return ret;
|
||||
|
||||
ret = devm_spi_register_controller(&pdev->dev, host);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
return devm_spi_register_controller(&pdev->dev, host);
|
||||
}
|
||||
|
||||
static const struct of_device_id clps711x_spi_dt_ids[] = {
|
||||
|
|
|
|||
|
|
@ -353,39 +353,33 @@ static int mcfqspi_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*mcfqspi));
|
||||
if (host == NULL) {
|
||||
dev_dbg(&pdev->dev, "spi_alloc_host failed\n");
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*mcfqspi));
|
||||
if (host == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mcfqspi = spi_controller_get_devdata(host);
|
||||
|
||||
mcfqspi->iobase = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(mcfqspi->iobase)) {
|
||||
status = PTR_ERR(mcfqspi->iobase);
|
||||
goto fail0;
|
||||
}
|
||||
if (IS_ERR(mcfqspi->iobase))
|
||||
return PTR_ERR(mcfqspi->iobase);
|
||||
|
||||
mcfqspi->irq = platform_get_irq(pdev, 0);
|
||||
if (mcfqspi->irq < 0) {
|
||||
dev_dbg(&pdev->dev, "platform_get_irq failed\n");
|
||||
status = -ENXIO;
|
||||
goto fail0;
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
status = devm_request_irq(&pdev->dev, mcfqspi->irq, mcfqspi_irq_handler,
|
||||
0, pdev->name, mcfqspi);
|
||||
if (status) {
|
||||
dev_dbg(&pdev->dev, "request_irq failed\n");
|
||||
goto fail0;
|
||||
return status;
|
||||
}
|
||||
|
||||
mcfqspi->clk = devm_clk_get_enabled(&pdev->dev, "qspi_clk");
|
||||
if (IS_ERR(mcfqspi->clk)) {
|
||||
dev_dbg(&pdev->dev, "clk_get failed\n");
|
||||
status = PTR_ERR(mcfqspi->clk);
|
||||
goto fail0;
|
||||
return PTR_ERR(mcfqspi->clk);
|
||||
}
|
||||
|
||||
host->bus_num = pdata->bus_num;
|
||||
|
|
@ -395,7 +389,7 @@ static int mcfqspi_probe(struct platform_device *pdev)
|
|||
status = mcfqspi_cs_setup(mcfqspi);
|
||||
if (status) {
|
||||
dev_dbg(&pdev->dev, "error initializing cs_control\n");
|
||||
goto fail0;
|
||||
return status;
|
||||
}
|
||||
|
||||
init_waitqueue_head(&mcfqspi->waitq);
|
||||
|
|
@ -423,8 +417,6 @@ static int mcfqspi_probe(struct platform_device *pdev)
|
|||
fail1:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
mcfqspi_cs_teardown(mcfqspi);
|
||||
fail0:
|
||||
spi_controller_put(host);
|
||||
|
||||
dev_dbg(&pdev->dev, "Coldfire QSPI probe failed\n");
|
||||
|
||||
|
|
@ -436,8 +428,6 @@ static void mcfqspi_remove(struct platform_device *pdev)
|
|||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct mcfqspi *mcfqspi = spi_controller_get_devdata(host);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
|
@ -445,8 +435,6 @@ static void mcfqspi_remove(struct platform_device *pdev)
|
|||
mcfqspi_wr_qmr(mcfqspi, MCFQSPI_QMR_MSTR);
|
||||
|
||||
mcfqspi_cs_teardown(mcfqspi);
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
|
|||
|
|
@ -438,8 +438,8 @@ static int cs42l43_spi_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
static const struct platform_device_id cs42l43_spi_id_table[] = {
|
||||
{ "cs42l43-spi", },
|
||||
{}
|
||||
{ .name = "cs42l43-spi" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, cs42l43_spi_id_table);
|
||||
|
||||
|
|
|
|||
|
|
@ -684,7 +684,7 @@ static int dln2_spi_probe(struct platform_device *pdev)
|
|||
struct dln2_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
int ret;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*dln2));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*dln2));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -693,10 +693,8 @@ static int dln2_spi_probe(struct platform_device *pdev)
|
|||
dln2 = spi_controller_get_devdata(host);
|
||||
|
||||
dln2->buf = devm_kmalloc(&pdev->dev, DLN2_SPI_BUF_SIZE, GFP_KERNEL);
|
||||
if (!dln2->buf) {
|
||||
ret = -ENOMEM;
|
||||
goto exit_free_host;
|
||||
}
|
||||
if (!dln2->buf)
|
||||
return -ENOMEM;
|
||||
|
||||
dln2->host = host;
|
||||
dln2->pdev = pdev;
|
||||
|
|
@ -709,13 +707,13 @@ static int dln2_spi_probe(struct platform_device *pdev)
|
|||
ret = dln2_spi_enable(dln2, false);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to disable SPI module\n");
|
||||
goto exit_free_host;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dln2_spi_get_cs_num(dln2, &host->num_chipselect);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to get number of CS pins\n");
|
||||
goto exit_free_host;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dln2_spi_get_speed_range(dln2,
|
||||
|
|
@ -723,20 +721,20 @@ static int dln2_spi_probe(struct platform_device *pdev)
|
|||
&host->max_speed_hz);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to read bus min/max freqs\n");
|
||||
goto exit_free_host;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dln2_spi_get_supported_frame_sizes(dln2,
|
||||
&host->bits_per_word_mask);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to read supported frame sizes\n");
|
||||
goto exit_free_host;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dln2_spi_cs_enable_all(dln2, true);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to enable CS pins\n");
|
||||
goto exit_free_host;
|
||||
return ret;
|
||||
}
|
||||
|
||||
host->bus_num = -1;
|
||||
|
|
@ -749,7 +747,7 @@ static int dln2_spi_probe(struct platform_device *pdev)
|
|||
ret = dln2_spi_enable(dln2, true);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to enable SPI module\n");
|
||||
goto exit_free_host;
|
||||
return ret;
|
||||
}
|
||||
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev,
|
||||
|
|
@ -772,8 +770,6 @@ static int dln2_spi_probe(struct platform_device *pdev)
|
|||
|
||||
if (dln2_spi_enable(dln2, false) < 0)
|
||||
dev_err(&pdev->dev, "Failed to disable SPI module\n");
|
||||
exit_free_host:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -783,16 +779,12 @@ static void dln2_spi_remove(struct platform_device *pdev)
|
|||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct dln2_spi *dln2 = spi_controller_get_devdata(host);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
if (dln2_spi_enable(dln2, false) < 0)
|
||||
dev_err(&pdev->dev, "Failed to disable SPI module\n");
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
|
|||
|
|
@ -1034,6 +1034,8 @@ void dw_spi_remove_controller(struct dw_spi *dws)
|
|||
dw_spi_shutdown_chip(dws);
|
||||
|
||||
free_irq(dws->irq, dws->ctlr);
|
||||
|
||||
spi_controller_put(dws->ctlr);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(dw_spi_remove_controller, "SPI_DW_CORE");
|
||||
|
||||
|
|
|
|||
|
|
@ -226,8 +226,8 @@ static int dw_spi_hssi_init(struct platform_device *pdev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dw_spi_intel_init(struct platform_device *pdev,
|
||||
struct dw_spi_mmio *dwsmmio)
|
||||
static int dw_spi_hssi_no_dma_init(struct platform_device *pdev,
|
||||
struct dw_spi_mmio *dwsmmio)
|
||||
{
|
||||
dwsmmio->dws.ip = DW_HSSI_ID;
|
||||
|
||||
|
|
@ -438,7 +438,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
|
|||
{ .compatible = "amazon,alpine-dw-apb-ssi", .data = dw_spi_alpine_init},
|
||||
{ .compatible = "renesas,rzn1-spi", .data = dw_spi_pssi_init},
|
||||
{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_hssi_init},
|
||||
{ .compatible = "intel,keembay-ssi", .data = dw_spi_intel_init},
|
||||
{ .compatible = "intel,keembay-ssi", .data = dw_spi_hssi_no_dma_init},
|
||||
{
|
||||
.compatible = "intel,mountevans-imc-ssi",
|
||||
.data = dw_spi_mountevans_imc_init,
|
||||
|
|
@ -453,6 +453,7 @@ MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
|
|||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_device_id dw_spi_mmio_acpi_match[] = {
|
||||
{"HISI0173", (kernel_ulong_t)dw_spi_pssi_init},
|
||||
{"LECA0002", (kernel_ulong_t)dw_spi_hssi_no_dma_init},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, dw_spi_mmio_acpi_match);
|
||||
|
|
|
|||
|
|
@ -120,16 +120,15 @@ static int dw_spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *en
|
|||
if (desc->setup) {
|
||||
ret = desc->setup(dws);
|
||||
if (ret)
|
||||
goto err_free_irq_vectors;
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
ret = -ENODEV;
|
||||
goto err_free_irq_vectors;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = dw_spi_add_controller(&pdev->dev, dws);
|
||||
if (ret)
|
||||
goto err_free_irq_vectors;
|
||||
return ret;
|
||||
|
||||
/* PCI hook and SPI hook use the same drv data */
|
||||
pci_set_drvdata(pdev, dws);
|
||||
|
|
@ -143,10 +142,6 @@ static int dw_spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *en
|
|||
pm_runtime_allow(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_irq_vectors:
|
||||
pci_free_irq_vectors(pdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dw_spi_pci_remove(struct pci_dev *pdev)
|
||||
|
|
@ -157,7 +152,6 @@ static void dw_spi_pci_remove(struct pci_dev *pdev)
|
|||
pm_runtime_get_noresume(&pdev->dev);
|
||||
|
||||
dw_spi_remove_controller(dws);
|
||||
pci_free_irq_vectors(pdev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
@ -185,15 +179,15 @@ static const struct pci_device_id dw_spi_pci_ids[] = {
|
|||
* exclusively used by SCU to communicate with MSIC.
|
||||
*/
|
||||
/* Intel MID platform SPI controller 1 */
|
||||
{ PCI_VDEVICE(INTEL, 0x0800), (kernel_ulong_t)&dw_spi_pci_mid_desc_1},
|
||||
{ PCI_VDEVICE(INTEL, 0x0800), .driver_data = (kernel_ulong_t)&dw_spi_pci_mid_desc_1 },
|
||||
/* Intel MID platform SPI controller 2 */
|
||||
{ PCI_VDEVICE(INTEL, 0x0812), (kernel_ulong_t)&dw_spi_pci_mid_desc_2},
|
||||
{ PCI_VDEVICE(INTEL, 0x0812), .driver_data = (kernel_ulong_t)&dw_spi_pci_mid_desc_2 },
|
||||
/* Intel Elkhart Lake PSE SPI controllers */
|
||||
{ PCI_VDEVICE(INTEL, 0x4b84), (kernel_ulong_t)&dw_spi_pci_ehl_desc},
|
||||
{ PCI_VDEVICE(INTEL, 0x4b85), (kernel_ulong_t)&dw_spi_pci_ehl_desc},
|
||||
{ PCI_VDEVICE(INTEL, 0x4b86), (kernel_ulong_t)&dw_spi_pci_ehl_desc},
|
||||
{ PCI_VDEVICE(INTEL, 0x4b87), (kernel_ulong_t)&dw_spi_pci_ehl_desc},
|
||||
{},
|
||||
{ PCI_VDEVICE(INTEL, 0x4b84), .driver_data = (kernel_ulong_t)&dw_spi_pci_ehl_desc },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b85), .driver_data = (kernel_ulong_t)&dw_spi_pci_ehl_desc },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b86), .driver_data = (kernel_ulong_t)&dw_spi_pci_ehl_desc },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b87), .driver_data = (kernel_ulong_t)&dw_spi_pci_ehl_desc },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, dw_spi_pci_ids);
|
||||
|
||||
|
|
|
|||
|
|
@ -600,6 +600,7 @@ static int ep93xx_spi_setup_dma(struct device *dev, struct ep93xx_spi *espi)
|
|||
espi->dma_rx = NULL;
|
||||
fail_free_page:
|
||||
free_page((unsigned long)espi->zeropage);
|
||||
espi->zeropage = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -631,7 +632,7 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
|
|||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*espi));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*espi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -656,8 +657,7 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
|
|||
espi->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(espi->clk)) {
|
||||
dev_err(&pdev->dev, "unable to get spi clock\n");
|
||||
error = PTR_ERR(espi->clk);
|
||||
goto fail_release_host;
|
||||
return PTR_ERR(espi->clk);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -668,22 +668,21 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
|
|||
host->min_speed_hz = clk_get_rate(espi->clk) / (254 * 256);
|
||||
|
||||
espi->mmio = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
if (IS_ERR(espi->mmio)) {
|
||||
error = PTR_ERR(espi->mmio);
|
||||
goto fail_release_host;
|
||||
}
|
||||
if (IS_ERR(espi->mmio))
|
||||
return PTR_ERR(espi->mmio);
|
||||
|
||||
espi->sspdr_phys = res->start + SSPDR;
|
||||
|
||||
error = devm_request_irq(&pdev->dev, irq, ep93xx_spi_interrupt,
|
||||
0, "ep93xx-spi", host);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to request irq\n");
|
||||
goto fail_release_host;
|
||||
return error;
|
||||
}
|
||||
|
||||
error = ep93xx_spi_setup_dma(&pdev->dev, espi);
|
||||
if (error == -EPROBE_DEFER)
|
||||
goto fail_release_host;
|
||||
return error;
|
||||
|
||||
if (error)
|
||||
dev_warn(&pdev->dev, "DMA setup failed. Falling back to PIO\n");
|
||||
|
|
@ -704,8 +703,6 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
|
|||
|
||||
fail_free_dma:
|
||||
ep93xx_spi_release_dma(espi);
|
||||
fail_release_host:
|
||||
spi_controller_put(host);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
|
@ -715,13 +712,9 @@ static void ep93xx_spi_remove(struct platform_device *pdev)
|
|||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct ep93xx_spi *espi = spi_controller_get_devdata(host);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
ep93xx_spi_release_dma(espi);
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
static const struct of_device_id ep93xx_spi_of_ids[] = {
|
||||
|
|
|
|||
|
|
@ -392,9 +392,8 @@ static int falcon_sflash_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct falcon_sflash *priv;
|
||||
struct spi_controller *host;
|
||||
int ret;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*priv));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*priv));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -406,10 +405,7 @@ static int falcon_sflash_probe(struct platform_device *pdev)
|
|||
host->setup = falcon_sflash_setup;
|
||||
host->transfer_one_message = falcon_sflash_xfer_one;
|
||||
|
||||
ret = devm_spi_register_controller(&pdev->dev, host);
|
||||
if (ret)
|
||||
spi_controller_put(host);
|
||||
return ret;
|
||||
return devm_spi_register_controller(&pdev->dev, host);
|
||||
}
|
||||
|
||||
static const struct of_device_id falcon_sflash_match[] = {
|
||||
|
|
|
|||
|
|
@ -554,7 +554,7 @@ static int fsi_spi_probe(struct fsi_device *fsi)
|
|||
if (of_property_read_u32(np, "reg", &base))
|
||||
continue;
|
||||
|
||||
ctlr = spi_alloc_host(dev, sizeof(*ctx));
|
||||
ctlr = devm_spi_alloc_host(dev, sizeof(*ctx));
|
||||
if (!ctlr)
|
||||
break;
|
||||
|
||||
|
|
@ -571,9 +571,9 @@ static int fsi_spi_probe(struct fsi_device *fsi)
|
|||
|
||||
rc = devm_spi_register_controller(dev, ctlr);
|
||||
if (rc)
|
||||
spi_controller_put(ctlr);
|
||||
else
|
||||
num_controllers_registered++;
|
||||
continue;
|
||||
|
||||
num_controllers_registered++;
|
||||
}
|
||||
|
||||
if (!num_controllers_registered)
|
||||
|
|
|
|||
|
|
@ -1715,6 +1715,8 @@ static void dspi_remove(struct platform_device *pdev)
|
|||
dspi_release_dma(dspi);
|
||||
if (dspi->irq)
|
||||
free_irq(dspi->irq, dspi);
|
||||
|
||||
spi_controller_put(dspi->ctlr);
|
||||
}
|
||||
|
||||
static void dspi_shutdown(struct platform_device *pdev)
|
||||
|
|
|
|||
|
|
@ -667,7 +667,7 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem,
|
|||
struct fsl_espi *espi;
|
||||
int ret;
|
||||
|
||||
host = spi_alloc_host(dev, sizeof(struct fsl_espi));
|
||||
host = devm_spi_alloc_host(dev, sizeof(struct fsl_espi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -690,8 +690,7 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem,
|
|||
espi->spibrg = fsl_get_sys_freq();
|
||||
if (espi->spibrg == -1) {
|
||||
dev_err(dev, "Can't get sys frequency!\n");
|
||||
ret = -EINVAL;
|
||||
goto err_probe;
|
||||
return -EINVAL;
|
||||
}
|
||||
/* determined by clock divider fields DIV16/PM in register SPMODEx */
|
||||
host->min_speed_hz = DIV_ROUND_UP(espi->spibrg, 4 * 16 * 16);
|
||||
|
|
@ -700,15 +699,13 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem,
|
|||
init_completion(&espi->done);
|
||||
|
||||
espi->reg_base = devm_ioremap_resource(dev, mem);
|
||||
if (IS_ERR(espi->reg_base)) {
|
||||
ret = PTR_ERR(espi->reg_base);
|
||||
goto err_probe;
|
||||
}
|
||||
if (IS_ERR(espi->reg_base))
|
||||
return PTR_ERR(espi->reg_base);
|
||||
|
||||
/* Register for SPI Interrupt */
|
||||
ret = devm_request_irq(dev, irq, fsl_espi_irq, 0, "fsl_espi", espi);
|
||||
if (ret)
|
||||
goto err_probe;
|
||||
return ret;
|
||||
|
||||
fsl_espi_init_regs(dev, true);
|
||||
|
||||
|
|
@ -732,8 +729,7 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem,
|
|||
pm_runtime_put_noidle(dev);
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_suspended(dev);
|
||||
err_probe:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -760,7 +756,7 @@ static int of_fsl_espi_probe(struct platform_device *ofdev)
|
|||
unsigned int irq, num_cs;
|
||||
int ret;
|
||||
|
||||
if (of_property_read_bool(np, "mode")) {
|
||||
if (of_property_present(np, "mode")) {
|
||||
dev_err(dev, "mode property is not supported on ESPI!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -784,13 +780,9 @@ static void of_fsl_espi_remove(struct platform_device *dev)
|
|||
{
|
||||
struct spi_controller *host = platform_get_drvdata(dev);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
pm_runtime_disable(&dev->dev);
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
|
|||
|
|
@ -647,7 +647,7 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
|
|||
tx->sgl, tx->nents, DMA_MEM_TO_DEV,
|
||||
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||
if (!desc_tx) {
|
||||
dmaengine_terminate_all(controller->dma_tx);
|
||||
dmaengine_terminate_sync(controller->dma_rx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -668,8 +668,8 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
|
|||
transfer_timeout);
|
||||
if (!time_left) {
|
||||
dev_err(fsl_lpspi->dev, "I/O Error in DMA TX\n");
|
||||
dmaengine_terminate_all(controller->dma_tx);
|
||||
dmaengine_terminate_all(controller->dma_rx);
|
||||
dmaengine_terminate_sync(controller->dma_tx);
|
||||
dmaengine_terminate_sync(controller->dma_rx);
|
||||
fsl_lpspi_reset(fsl_lpspi);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
|
@ -678,8 +678,8 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
|
|||
transfer_timeout);
|
||||
if (!time_left) {
|
||||
dev_err(fsl_lpspi->dev, "I/O Error in DMA RX\n");
|
||||
dmaengine_terminate_all(controller->dma_tx);
|
||||
dmaengine_terminate_all(controller->dma_rx);
|
||||
dmaengine_terminate_sync(controller->dma_tx);
|
||||
dmaengine_terminate_sync(controller->dma_rx);
|
||||
fsl_lpspi_reset(fsl_lpspi);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
|
@ -688,8 +688,8 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
|
|||
fsl_lpspi->target_aborted) {
|
||||
dev_dbg(fsl_lpspi->dev,
|
||||
"I/O Error in DMA TX interrupted\n");
|
||||
dmaengine_terminate_all(controller->dma_tx);
|
||||
dmaengine_terminate_all(controller->dma_rx);
|
||||
dmaengine_terminate_sync(controller->dma_tx);
|
||||
dmaengine_terminate_sync(controller->dma_rx);
|
||||
fsl_lpspi_reset(fsl_lpspi);
|
||||
return -EINTR;
|
||||
}
|
||||
|
|
@ -698,8 +698,8 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
|
|||
fsl_lpspi->target_aborted) {
|
||||
dev_dbg(fsl_lpspi->dev,
|
||||
"I/O Error in DMA RX interrupted\n");
|
||||
dmaengine_terminate_all(controller->dma_tx);
|
||||
dmaengine_terminate_all(controller->dma_rx);
|
||||
dmaengine_terminate_sync(controller->dma_tx);
|
||||
dmaengine_terminate_sync(controller->dma_rx);
|
||||
fsl_lpspi_reset(fsl_lpspi);
|
||||
return -EINTR;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -535,7 +535,7 @@ static struct spi_controller *fsl_spi_probe(struct device *dev,
|
|||
u32 regval;
|
||||
int ret = 0;
|
||||
|
||||
host = spi_alloc_host(dev, sizeof(struct mpc8xxx_spi));
|
||||
host = devm_spi_alloc_host(dev, sizeof(struct mpc8xxx_spi));
|
||||
if (host == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
|
|
@ -559,7 +559,7 @@ static struct spi_controller *fsl_spi_probe(struct device *dev,
|
|||
|
||||
ret = fsl_spi_cpm_init(mpc8xxx_spi);
|
||||
if (ret)
|
||||
goto err_cpm_init;
|
||||
goto err;
|
||||
|
||||
mpc8xxx_spi->reg_base = devm_ioremap_resource(dev, mem);
|
||||
if (IS_ERR(mpc8xxx_spi->reg_base)) {
|
||||
|
|
@ -625,8 +625,6 @@ static struct spi_controller *fsl_spi_probe(struct device *dev,
|
|||
|
||||
err_probe:
|
||||
fsl_spi_cpm_free(mpc8xxx_spi);
|
||||
err_cpm_init:
|
||||
spi_controller_put(host);
|
||||
err:
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
|
@ -705,13 +703,9 @@ static void of_fsl_spi_remove(struct platform_device *ofdev)
|
|||
struct spi_controller *host = platform_get_drvdata(ofdev);
|
||||
struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(host);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
fsl_spi_cpm_free(mpc8xxx_spi);
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
static struct platform_driver of_fsl_spi_driver = {
|
||||
|
|
@ -757,13 +751,9 @@ static void plat_mpc8xxx_spi_remove(struct platform_device *pdev)
|
|||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(host);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
fsl_spi_cpm_free(mpc8xxx_spi);
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
MODULE_ALIAS("platform:mpc8xxx_spi");
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (c) 2017-2018, The Linux foundation. All rights reserved.
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/qcom_geni_spi.h>
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
|
@ -332,6 +335,9 @@ static int geni_spi_set_clock_and_bw(struct spi_geni_master *mas,
|
|||
writel(clk_sel, se->base + SE_GENI_CLK_SEL);
|
||||
writel(m_clk_cfg, se->base + GENI_SER_M_CLK_CFG);
|
||||
|
||||
trace_geni_spi_clk_cfg(mas->dev, clk_hz, mas->cur_sclk_hz, idx, div,
|
||||
mas->cur_bits_per_word);
|
||||
|
||||
/* Set BW quota for CPU as driver supports FIFO mode only. */
|
||||
se->icc_paths[CPU_TO_GENI].avg_bw = Bps_to_icc(mas->cur_speed_hz);
|
||||
ret = geni_icc_set_bw(se);
|
||||
|
|
@ -366,6 +372,9 @@ static int setup_fifo_params(struct spi_device *spi_slv,
|
|||
if ((mode_changed & SPI_CS_HIGH) || (cs_changed && (spi_slv->mode & SPI_CS_HIGH)))
|
||||
writel((spi_slv->mode & SPI_CS_HIGH) ? BIT(chipselect) : 0, se->base + SE_SPI_DEMUX_OUTPUT_INV);
|
||||
|
||||
trace_geni_spi_setup_params(mas->dev, chipselect, spi_slv->mode,
|
||||
mode_changed, cs_changed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -872,6 +881,8 @@ static int setup_se_xfer(struct spi_transfer *xfer,
|
|||
spin_lock_irq(&mas->lock);
|
||||
geni_se_setup_m_cmd(se, m_cmd, m_params);
|
||||
|
||||
trace_geni_spi_transfer(mas->dev, len, m_cmd);
|
||||
|
||||
if (mas->cur_xfer_mode == GENI_SE_DMA) {
|
||||
if (m_cmd & SPI_RX_ONLY)
|
||||
geni_se_rx_init_dma(se, sg_dma_address(xfer->rx_sg.sgl),
|
||||
|
|
@ -926,6 +937,8 @@ static irqreturn_t geni_spi_isr(int irq, void *data)
|
|||
if (!m_irq && !dma_tx_status && !dma_rx_status)
|
||||
return IRQ_NONE;
|
||||
|
||||
trace_geni_spi_irq(mas->dev, m_irq, dma_tx_status, dma_rx_status);
|
||||
|
||||
if (m_irq & (M_CMD_OVERRUN_EN | M_ILLEGAL_CMD_EN | M_CMD_FAILURE_EN |
|
||||
M_RX_FIFO_RD_ERR_EN | M_RX_FIFO_WR_ERR_EN |
|
||||
M_TX_FIFO_RD_ERR_EN | M_TX_FIFO_WR_ERR_EN))
|
||||
|
|
|
|||
|
|
@ -463,6 +463,7 @@ static int hisi_spi_probe(struct platform_device *pdev)
|
|||
struct device *dev = &pdev->dev;
|
||||
struct spi_controller *host;
|
||||
struct hisi_spi *hs;
|
||||
u32 num_cs;
|
||||
int ret, irq;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
|
|
@ -495,10 +496,11 @@ static int hisi_spi_probe(struct platform_device *pdev)
|
|||
if (host->max_speed_hz == 0)
|
||||
return dev_err_probe(dev, -EINVAL, "spi-max-frequency can't be 0\n");
|
||||
|
||||
ret = device_property_read_u16(dev, "num-cs",
|
||||
&host->num_chipselect);
|
||||
ret = device_property_read_u32(dev, "num-cs", &num_cs);
|
||||
if (ret)
|
||||
host->num_chipselect = DEFAULT_NUM_CS;
|
||||
else
|
||||
host->num_chipselect = num_cs;
|
||||
|
||||
host->use_gpio_descriptors = true;
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
|
||||
|
|
@ -520,10 +522,8 @@ static int hisi_spi_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
ret = spi_register_controller(host);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to register spi host, ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to register spi host\n");
|
||||
|
||||
if (hisi_spi_debugfs_init(hs))
|
||||
dev_info(dev, "failed to create debugfs dir\n");
|
||||
|
|
|
|||
|
|
@ -436,7 +436,7 @@ static int hisi_sfc_v3xx_probe(struct platform_device *pdev)
|
|||
u32 version, glb_config;
|
||||
int ret;
|
||||
|
||||
ctlr = spi_alloc_host(&pdev->dev, sizeof(*host));
|
||||
ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*host));
|
||||
if (!ctlr)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -451,16 +451,12 @@ static int hisi_sfc_v3xx_probe(struct platform_device *pdev)
|
|||
platform_set_drvdata(pdev, host);
|
||||
|
||||
host->regbase = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(host->regbase)) {
|
||||
ret = PTR_ERR(host->regbase);
|
||||
goto err_put_host;
|
||||
}
|
||||
if (IS_ERR(host->regbase))
|
||||
return PTR_ERR(host->regbase);
|
||||
|
||||
host->irq = platform_get_irq_optional(pdev, 0);
|
||||
if (host->irq == -EPROBE_DEFER) {
|
||||
ret = -EPROBE_DEFER;
|
||||
goto err_put_host;
|
||||
}
|
||||
if (host->irq == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
hisi_sfc_v3xx_disable_int(host);
|
||||
|
||||
|
|
@ -501,16 +497,12 @@ static int hisi_sfc_v3xx_probe(struct platform_device *pdev)
|
|||
|
||||
ret = devm_spi_register_controller(dev, ctlr);
|
||||
if (ret)
|
||||
goto err_put_host;
|
||||
return ret;
|
||||
|
||||
dev_info(&pdev->dev, "hw version 0x%x, %s mode.\n",
|
||||
version, host->irq ? "irq" : "polling");
|
||||
|
||||
return 0;
|
||||
|
||||
err_put_host:
|
||||
spi_controller_put(ctlr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct acpi_device_id hisi_sfc_v3xx_acpi_ids[] = {
|
||||
|
|
|
|||
|
|
@ -530,7 +530,7 @@ static int img_spfi_probe(struct platform_device *pdev)
|
|||
int ret;
|
||||
u32 max_speed_hz;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*spfi));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*spfi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
|
@ -541,36 +541,32 @@ static int img_spfi_probe(struct platform_device *pdev)
|
|||
spin_lock_init(&spfi->lock);
|
||||
|
||||
spfi->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
if (IS_ERR(spfi->regs)) {
|
||||
ret = PTR_ERR(spfi->regs);
|
||||
goto put_spi;
|
||||
}
|
||||
if (IS_ERR(spfi->regs))
|
||||
return PTR_ERR(spfi->regs);
|
||||
|
||||
spfi->phys = res->start;
|
||||
|
||||
spfi->irq = platform_get_irq(pdev, 0);
|
||||
if (spfi->irq < 0) {
|
||||
ret = spfi->irq;
|
||||
goto put_spi;
|
||||
}
|
||||
if (spfi->irq < 0)
|
||||
return spfi->irq;
|
||||
|
||||
ret = devm_request_irq(spfi->dev, spfi->irq, img_spfi_irq,
|
||||
IRQ_TYPE_LEVEL_HIGH, dev_name(spfi->dev), spfi);
|
||||
if (ret)
|
||||
goto put_spi;
|
||||
return ret;
|
||||
|
||||
spfi->sys_clk = devm_clk_get(spfi->dev, "sys");
|
||||
if (IS_ERR(spfi->sys_clk)) {
|
||||
ret = PTR_ERR(spfi->sys_clk);
|
||||
goto put_spi;
|
||||
}
|
||||
if (IS_ERR(spfi->sys_clk))
|
||||
return PTR_ERR(spfi->sys_clk);
|
||||
|
||||
spfi->spfi_clk = devm_clk_get(spfi->dev, "spfi");
|
||||
if (IS_ERR(spfi->spfi_clk)) {
|
||||
ret = PTR_ERR(spfi->spfi_clk);
|
||||
goto put_spi;
|
||||
}
|
||||
if (IS_ERR(spfi->spfi_clk))
|
||||
return PTR_ERR(spfi->spfi_clk);
|
||||
|
||||
ret = clk_prepare_enable(spfi->sys_clk);
|
||||
if (ret)
|
||||
goto put_spi;
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(spfi->spfi_clk);
|
||||
if (ret)
|
||||
goto disable_pclk;
|
||||
|
|
@ -658,8 +654,6 @@ static int img_spfi_probe(struct platform_device *pdev)
|
|||
clk_disable_unprepare(spfi->spfi_clk);
|
||||
disable_pclk:
|
||||
clk_disable_unprepare(spfi->sys_clk);
|
||||
put_spi:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -669,8 +663,6 @@ static void img_spfi_remove(struct platform_device *pdev)
|
|||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct img_spfi *spfi = spi_controller_get_devdata(host);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
if (spfi->tx_ch)
|
||||
|
|
@ -683,8 +675,6 @@ static void img_spfi_remove(struct platform_device *pdev)
|
|||
clk_disable_unprepare(spfi->spfi_clk);
|
||||
clk_disable_unprepare(spfi->sys_clk);
|
||||
}
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
|
|
|||
|
|
@ -1774,8 +1774,8 @@ static int spi_imx_dma_submit(struct spi_imx_data *spi_imx,
|
|||
transfer_timeout);
|
||||
if (!time_left) {
|
||||
dev_err(spi_imx->dev, "I/O Error in DMA TX\n");
|
||||
dmaengine_terminate_all(controller->dma_tx);
|
||||
dmaengine_terminate_all(controller->dma_rx);
|
||||
dmaengine_terminate_sync(controller->dma_tx);
|
||||
dmaengine_terminate_sync(controller->dma_rx);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
|
|
@ -1784,7 +1784,7 @@ static int spi_imx_dma_submit(struct spi_imx_data *spi_imx,
|
|||
if (!time_left) {
|
||||
dev_err(&controller->dev, "I/O Error in DMA RX\n");
|
||||
spi_imx->devtype_data->reset(spi_imx);
|
||||
dmaengine_terminate_all(controller->dma_rx);
|
||||
dmaengine_terminate_sync(controller->dma_rx);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -1793,15 +1793,15 @@ static int spi_imx_dma_submit(struct spi_imx_data *spi_imx,
|
|||
if (wait_for_completion_interruptible(&spi_imx->dma_tx_completion) ||
|
||||
READ_ONCE(spi_imx->target_aborted)) {
|
||||
dev_dbg(spi_imx->dev, "I/O Error in DMA TX interrupted\n");
|
||||
dmaengine_terminate_all(controller->dma_tx);
|
||||
dmaengine_terminate_all(controller->dma_rx);
|
||||
dmaengine_terminate_sync(controller->dma_tx);
|
||||
dmaengine_terminate_sync(controller->dma_rx);
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
if (wait_for_completion_interruptible(&spi_imx->dma_rx_completion) ||
|
||||
READ_ONCE(spi_imx->target_aborted)) {
|
||||
dev_dbg(spi_imx->dev, "I/O Error in DMA RX interrupted\n");
|
||||
dmaengine_terminate_all(controller->dma_rx);
|
||||
dmaengine_terminate_sync(controller->dma_rx);
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
|
|
@ -1818,9 +1818,9 @@ static int spi_imx_dma_submit(struct spi_imx_data *spi_imx,
|
|||
return 0;
|
||||
|
||||
dmaengine_terminate_tx:
|
||||
dmaengine_terminate_all(controller->dma_tx);
|
||||
dmaengine_terminate_sync(controller->dma_tx);
|
||||
dmaengine_terminate_rx:
|
||||
dmaengine_terminate_all(controller->dma_rx);
|
||||
dmaengine_terminate_sync(controller->dma_rx);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,39 +66,39 @@ static int intel_spi_pci_probe(struct pci_dev *pdev,
|
|||
}
|
||||
|
||||
static const struct pci_device_id intel_spi_pci_ids[] = {
|
||||
{ PCI_VDEVICE(INTEL, 0x02a4), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x06a4), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x18e0), (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x1bca), (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x34a4), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x38a4), (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x43a4), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b24), (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4d23), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4da4), (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x51a4), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x54a4), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x5794), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x5825), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x6e24), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x7723), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x7a24), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x7aa4), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x7e23), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x7f24), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x9d24), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x9da4), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa0a4), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa1a4), (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa224), (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa2a4), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa324), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa3a4), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa823), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xd323), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xe323), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xe423), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x02a4), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x06a4), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x18e0), .driver_data = (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x19e0), .driver_data = (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x1bca), .driver_data = (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x34a4), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x38a4), .driver_data = (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x43a4), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b24), .driver_data = (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4d23), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4da4), .driver_data = (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x51a4), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x54a4), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x5794), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x5825), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x6e24), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x7723), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x7a24), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x7aa4), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x7e23), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x7f24), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x9d24), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x9da4), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa0a4), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa1a4), .driver_data = (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa224), .driver_data = (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa2a4), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa324), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa3a4), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa823), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xd323), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xe323), .driver_data = (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xe423), .driver_data = (unsigned long)&cnl_info },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, intel_spi_pci_ids);
|
||||
|
|
|
|||
|
|
@ -814,7 +814,7 @@ static int intel_spi_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
|||
struct intel_spi *ispi = spi_controller_get_devdata(desc->mem->spi->controller);
|
||||
const struct intel_spi_mem_op *iop;
|
||||
|
||||
iop = intel_spi_match_mem_op(ispi, &desc->info.op_tmpl);
|
||||
iop = intel_spi_match_mem_op(ispi, desc->info.op_tmpl);
|
||||
if (!iop)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
|
|
@ -827,7 +827,7 @@ static ssize_t intel_spi_dirmap_read(struct spi_mem_dirmap_desc *desc, u64 offs,
|
|||
{
|
||||
struct intel_spi *ispi = spi_controller_get_devdata(desc->mem->spi->controller);
|
||||
const struct intel_spi_mem_op *iop = desc->priv;
|
||||
struct spi_mem_op op = desc->info.op_tmpl;
|
||||
struct spi_mem_op op = *desc->info.op_tmpl;
|
||||
int ret;
|
||||
|
||||
/* Fill in the gaps */
|
||||
|
|
@ -844,7 +844,7 @@ static ssize_t intel_spi_dirmap_write(struct spi_mem_dirmap_desc *desc, u64 offs
|
|||
{
|
||||
struct intel_spi *ispi = spi_controller_get_devdata(desc->mem->spi->controller);
|
||||
const struct intel_spi_mem_op *iop = desc->priv;
|
||||
struct spi_mem_op op = desc->info.op_tmpl;
|
||||
struct spi_mem_op op = *desc->info.op_tmpl;
|
||||
int ret;
|
||||
|
||||
op.addr.val = offs;
|
||||
|
|
|
|||
|
|
@ -146,11 +146,10 @@ static int jcore_spi_probe(struct platform_device *pdev)
|
|||
struct resource *res;
|
||||
u32 clock_freq;
|
||||
struct clk *clk;
|
||||
int err = -ENODEV;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(struct jcore_spi));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(struct jcore_spi));
|
||||
if (!host)
|
||||
return err;
|
||||
return -ENOMEM;
|
||||
|
||||
/* Setup the host state. */
|
||||
host->num_chipselect = 3;
|
||||
|
|
@ -167,14 +166,14 @@ static int jcore_spi_probe(struct platform_device *pdev)
|
|||
/* Find and map our resources */
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
goto exit_busy;
|
||||
return -EBUSY;
|
||||
if (!devm_request_mem_region(&pdev->dev, res->start,
|
||||
resource_size(res), pdev->name))
|
||||
goto exit_busy;
|
||||
return -EBUSY;
|
||||
hw->base = devm_ioremap(&pdev->dev, res->start,
|
||||
resource_size(res));
|
||||
if (!hw->base)
|
||||
goto exit_busy;
|
||||
return -EBUSY;
|
||||
|
||||
/*
|
||||
* The SPI clock rate controlled via a configurable clock divider
|
||||
|
|
@ -200,17 +199,7 @@ static int jcore_spi_probe(struct platform_device *pdev)
|
|||
jcore_spi_baudrate(hw, 400000);
|
||||
|
||||
/* Register our spi controller */
|
||||
err = devm_spi_register_controller(&pdev->dev, host);
|
||||
if (err)
|
||||
goto exit;
|
||||
|
||||
return 0;
|
||||
|
||||
exit_busy:
|
||||
err = -EBUSY;
|
||||
exit:
|
||||
spi_controller_put(host);
|
||||
return err;
|
||||
return devm_spi_register_controller(&pdev->dev, host);
|
||||
}
|
||||
|
||||
static const struct of_device_id jcore_spi_of_match[] = {
|
||||
|
|
|
|||
|
|
@ -913,7 +913,7 @@ static int lantiq_ssc_probe(struct platform_device *pdev)
|
|||
|
||||
hwcfg = of_device_get_match_data(dev);
|
||||
|
||||
host = spi_alloc_host(dev, sizeof(struct lantiq_ssc_spi));
|
||||
host = devm_spi_alloc_host(dev, sizeof(struct lantiq_ssc_spi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -923,20 +923,16 @@ static int lantiq_ssc_probe(struct platform_device *pdev)
|
|||
spi->hwcfg = hwcfg;
|
||||
platform_set_drvdata(pdev, spi);
|
||||
spi->regbase = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(spi->regbase)) {
|
||||
err = PTR_ERR(spi->regbase);
|
||||
goto err_host_put;
|
||||
}
|
||||
if (IS_ERR(spi->regbase))
|
||||
return PTR_ERR(spi->regbase);
|
||||
|
||||
err = hwcfg->cfg_irq(pdev, spi);
|
||||
if (err)
|
||||
goto err_host_put;
|
||||
return err;
|
||||
|
||||
spi->spi_clk = devm_clk_get_enabled(dev, "gate");
|
||||
if (IS_ERR(spi->spi_clk)) {
|
||||
err = PTR_ERR(spi->spi_clk);
|
||||
goto err_host_put;
|
||||
}
|
||||
if (IS_ERR(spi->spi_clk))
|
||||
return PTR_ERR(spi->spi_clk);
|
||||
|
||||
/*
|
||||
* Use the old clk_get_fpi() function on Lantiq platform, till it
|
||||
|
|
@ -947,10 +943,8 @@ static int lantiq_ssc_probe(struct platform_device *pdev)
|
|||
#else
|
||||
spi->fpi_clk = clk_get(dev, "freq");
|
||||
#endif
|
||||
if (IS_ERR(spi->fpi_clk)) {
|
||||
err = PTR_ERR(spi->fpi_clk);
|
||||
goto err_host_put;
|
||||
}
|
||||
if (IS_ERR(spi->fpi_clk))
|
||||
return PTR_ERR(spi->fpi_clk);
|
||||
|
||||
num_cs = 8;
|
||||
of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs);
|
||||
|
|
@ -1006,8 +1000,6 @@ static int lantiq_ssc_probe(struct platform_device *pdev)
|
|||
destroy_workqueue(spi->wq);
|
||||
err_clk_put:
|
||||
clk_put(spi->fpi_clk);
|
||||
err_host_put:
|
||||
spi_controller_put(host);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -1016,8 +1008,6 @@ static void lantiq_ssc_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct lantiq_ssc_spi *spi = platform_get_drvdata(pdev);
|
||||
|
||||
spi_controller_get(spi->host);
|
||||
|
||||
spi_unregister_controller(spi->host);
|
||||
|
||||
lantiq_ssc_writel(spi, 0, LTQ_SPI_IRNEN);
|
||||
|
|
@ -1028,8 +1018,6 @@ static void lantiq_ssc_remove(struct platform_device *pdev)
|
|||
|
||||
destroy_workqueue(spi->wq);
|
||||
clk_put(spi->fpi_clk);
|
||||
|
||||
spi_controller_put(spi->host);
|
||||
}
|
||||
|
||||
static struct platform_driver lantiq_ssc_driver = {
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ spi_lp8841_rtc_probe(struct platform_device *pdev)
|
|||
struct spi_controller *host;
|
||||
struct spi_lp8841_rtc *data;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*data));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*data));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
|
@ -199,8 +199,6 @@ spi_lp8841_rtc_probe(struct platform_device *pdev)
|
|||
host->set_cs = spi_lp8841_rtc_set_cs;
|
||||
host->transfer_one = spi_lp8841_rtc_transfer_one;
|
||||
host->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
#ifdef CONFIG_OF
|
||||
#endif
|
||||
|
||||
data = spi_controller_get_devdata(host);
|
||||
|
||||
|
|
@ -208,23 +206,17 @@ spi_lp8841_rtc_probe(struct platform_device *pdev)
|
|||
ret = PTR_ERR_OR_ZERO(data->iomem);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to get IO address\n");
|
||||
goto err_put_host;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* register with the SPI framework */
|
||||
ret = devm_spi_register_controller(&pdev->dev, host);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "cannot register spi host\n");
|
||||
goto err_put_host;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
|
||||
err_put_host:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_ALIAS("platform:" DRIVER_NAME);
|
||||
|
|
|
|||
|
|
@ -654,7 +654,7 @@ EXPORT_SYMBOL_GPL(spi_mem_calc_op_duration);
|
|||
static ssize_t spi_mem_no_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
||||
u64 offs, size_t len, void *buf)
|
||||
{
|
||||
struct spi_mem_op op = desc->info.op_tmpl;
|
||||
struct spi_mem_op op = *desc->info.op_tmpl;
|
||||
int ret;
|
||||
|
||||
op.addr.val = desc->info.offset + offs;
|
||||
|
|
@ -674,7 +674,7 @@ static ssize_t spi_mem_no_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
|||
static ssize_t spi_mem_no_dirmap_write(struct spi_mem_dirmap_desc *desc,
|
||||
u64 offs, size_t len, const void *buf)
|
||||
{
|
||||
struct spi_mem_op op = desc->info.op_tmpl;
|
||||
struct spi_mem_op op = *desc->info.op_tmpl;
|
||||
int ret;
|
||||
|
||||
op.addr.val = desc->info.offset + offs;
|
||||
|
|
@ -713,19 +713,37 @@ spi_mem_dirmap_create(struct spi_mem *mem,
|
|||
int ret = -ENOTSUPP;
|
||||
|
||||
/* Make sure the number of address cycles is between 1 and 8 bytes. */
|
||||
if (!info->op_tmpl.addr.nbytes || info->op_tmpl.addr.nbytes > 8)
|
||||
if (!info->primary_op_tmpl.addr.nbytes || info->primary_op_tmpl.addr.nbytes > 8)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* data.dir should either be SPI_MEM_DATA_IN or SPI_MEM_DATA_OUT. */
|
||||
if (info->op_tmpl.data.dir == SPI_MEM_NO_DATA)
|
||||
if (info->primary_op_tmpl.data.dir == SPI_MEM_NO_DATA)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* Apply similar constraints to the secondary template */
|
||||
if (info->secondary_op_tmpl.cmd.opcode) {
|
||||
if (!info->secondary_op_tmpl.addr.nbytes ||
|
||||
info->secondary_op_tmpl.addr.nbytes > 8)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (info->secondary_op_tmpl.data.dir == SPI_MEM_NO_DATA)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (!spi_mem_supports_op(mem, &info->secondary_op_tmpl))
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
|
||||
if (ctlr->mem_ops && ctlr->mem_ops->dirmap_create &&
|
||||
!spi_mem_controller_is_capable(ctlr, secondary_op_tmpl))
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
desc = kzalloc_obj(*desc);
|
||||
if (!desc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
desc->mem = mem;
|
||||
desc->info = *info;
|
||||
desc->info.op_tmpl = &desc->info.primary_op_tmpl;
|
||||
if (ctlr->mem_ops && ctlr->mem_ops->dirmap_create) {
|
||||
ret = spi_mem_access_start(mem);
|
||||
if (ret) {
|
||||
|
|
@ -740,7 +758,7 @@ spi_mem_dirmap_create(struct spi_mem *mem,
|
|||
|
||||
if (ret) {
|
||||
desc->nodirmap = true;
|
||||
if (!spi_mem_supports_op(desc->mem, &desc->info.op_tmpl))
|
||||
if (!spi_mem_supports_op(desc->mem, &desc->info.primary_op_tmpl))
|
||||
ret = -EOPNOTSUPP;
|
||||
else
|
||||
ret = 0;
|
||||
|
|
@ -864,7 +882,7 @@ ssize_t spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
|||
struct spi_controller *ctlr = desc->mem->spi->controller;
|
||||
ssize_t ret;
|
||||
|
||||
if (desc->info.op_tmpl.data.dir != SPI_MEM_DATA_IN)
|
||||
if (desc->info.op_tmpl->data.dir != SPI_MEM_DATA_IN)
|
||||
return -EINVAL;
|
||||
|
||||
if (!len)
|
||||
|
|
@ -910,7 +928,7 @@ ssize_t spi_mem_dirmap_write(struct spi_mem_dirmap_desc *desc,
|
|||
struct spi_controller *ctlr = desc->mem->spi->controller;
|
||||
ssize_t ret;
|
||||
|
||||
if (desc->info.op_tmpl.data.dir != SPI_MEM_DATA_OUT)
|
||||
if (desc->info.op_tmpl->data.dir != SPI_MEM_DATA_OUT)
|
||||
return -EINVAL;
|
||||
|
||||
if (!len)
|
||||
|
|
|
|||
|
|
@ -539,9 +539,8 @@ static void meson_spicc_setup_xfer(struct meson_spicc_device *spicc,
|
|||
conf = conf_orig = readl_relaxed(spicc->base + SPICC_CONREG);
|
||||
|
||||
/* Setup word width */
|
||||
conf &= ~SPICC_BITLENGTH_MASK;
|
||||
conf |= FIELD_PREP(SPICC_BITLENGTH_MASK,
|
||||
(spicc->bytes_per_word << 3) - 1);
|
||||
FIELD_MODIFY(SPICC_BITLENGTH_MASK, &conf,
|
||||
(spicc->bytes_per_word << 3) - 1);
|
||||
|
||||
/* Ignore if unchanged */
|
||||
if (conf != conf_orig)
|
||||
|
|
@ -982,7 +981,7 @@ static int meson_spicc_probe(struct platform_device *pdev)
|
|||
struct meson_spicc_device *spicc;
|
||||
int ret, irq;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*spicc));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*spicc));
|
||||
if (!host) {
|
||||
dev_err(&pdev->dev, "host allocation failed\n");
|
||||
return -ENOMEM;
|
||||
|
|
@ -993,8 +992,7 @@ static int meson_spicc_probe(struct platform_device *pdev)
|
|||
spicc->data = of_device_get_match_data(&pdev->dev);
|
||||
if (!spicc->data) {
|
||||
dev_err(&pdev->dev, "failed to get match data\n");
|
||||
ret = -EINVAL;
|
||||
goto out_host;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spicc->pdev = pdev;
|
||||
|
|
@ -1005,8 +1003,7 @@ static int meson_spicc_probe(struct platform_device *pdev)
|
|||
spicc->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(spicc->base)) {
|
||||
dev_err(&pdev->dev, "io resource mapping failed\n");
|
||||
ret = PTR_ERR(spicc->base);
|
||||
goto out_host;
|
||||
return PTR_ERR(spicc->base);
|
||||
}
|
||||
|
||||
/* Set master mode and enable controller */
|
||||
|
|
@ -1017,39 +1014,33 @@ static int meson_spicc_probe(struct platform_device *pdev)
|
|||
writel_relaxed(0, spicc->base + SPICC_INTREG);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
ret = irq;
|
||||
goto out_host;
|
||||
}
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, irq, meson_spicc_irq,
|
||||
0, NULL, spicc);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "irq request failed\n");
|
||||
goto out_host;
|
||||
return ret;
|
||||
}
|
||||
|
||||
spicc->core = devm_clk_get_enabled(&pdev->dev, "core");
|
||||
if (IS_ERR(spicc->core)) {
|
||||
dev_err(&pdev->dev, "core clock request failed\n");
|
||||
ret = PTR_ERR(spicc->core);
|
||||
goto out_host;
|
||||
return PTR_ERR(spicc->core);
|
||||
}
|
||||
|
||||
if (spicc->data->has_pclk) {
|
||||
spicc->pclk = devm_clk_get_enabled(&pdev->dev, "pclk");
|
||||
if (IS_ERR(spicc->pclk)) {
|
||||
dev_err(&pdev->dev, "pclk clock request failed\n");
|
||||
ret = PTR_ERR(spicc->pclk);
|
||||
goto out_host;
|
||||
return PTR_ERR(spicc->pclk);
|
||||
}
|
||||
}
|
||||
|
||||
spicc->pinctrl = devm_pinctrl_get(&pdev->dev);
|
||||
if (IS_ERR(spicc->pinctrl)) {
|
||||
ret = PTR_ERR(spicc->pinctrl);
|
||||
goto out_host;
|
||||
}
|
||||
if (IS_ERR(spicc->pinctrl))
|
||||
return PTR_ERR(spicc->pinctrl);
|
||||
|
||||
device_reset_optional(&pdev->dev);
|
||||
|
||||
|
|
@ -1070,43 +1061,34 @@ static int meson_spicc_probe(struct platform_device *pdev)
|
|||
ret = meson_spicc_pow2_clk_init(spicc);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "pow2 clock registration failed\n");
|
||||
goto out_host;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (spicc->data->has_enhance_clk_div) {
|
||||
ret = meson_spicc_enh_clk_init(spicc);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "clock registration failed\n");
|
||||
goto out_host;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = spi_register_controller(host);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "spi registration failed\n");
|
||||
goto out_host;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_host:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void meson_spicc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct meson_spicc_device *spicc = platform_get_drvdata(pdev);
|
||||
|
||||
spi_controller_get(spicc->host);
|
||||
|
||||
spi_unregister_controller(spicc->host);
|
||||
|
||||
/* Disable SPI */
|
||||
writel(0, spicc->base + SPICC_CONREG);
|
||||
|
||||
spi_controller_put(spicc->host);
|
||||
}
|
||||
|
||||
static const struct meson_spicc_data meson_spicc_gx_data = {
|
||||
|
|
|
|||
|
|
@ -288,9 +288,9 @@ static int meson_spifc_probe(struct platform_device *pdev)
|
|||
struct meson_spifc *spifc;
|
||||
void __iomem *base;
|
||||
unsigned int rate;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(struct meson_spifc));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(struct meson_spifc));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -300,23 +300,18 @@ static int meson_spifc_probe(struct platform_device *pdev)
|
|||
spifc->dev = &pdev->dev;
|
||||
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(base)) {
|
||||
ret = PTR_ERR(base);
|
||||
goto out_err;
|
||||
}
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
spifc->regmap = devm_regmap_init_mmio(spifc->dev, base,
|
||||
&spifc_regmap_config);
|
||||
if (IS_ERR(spifc->regmap)) {
|
||||
ret = PTR_ERR(spifc->regmap);
|
||||
goto out_err;
|
||||
}
|
||||
if (IS_ERR(spifc->regmap))
|
||||
return PTR_ERR(spifc->regmap);
|
||||
|
||||
spifc->clk = devm_clk_get_enabled(spifc->dev, NULL);
|
||||
if (IS_ERR(spifc->clk)) {
|
||||
dev_err(spifc->dev, "missing clock\n");
|
||||
ret = PTR_ERR(spifc->clk);
|
||||
goto out_err;
|
||||
return PTR_ERR(spifc->clk);
|
||||
}
|
||||
|
||||
rate = clk_get_rate(spifc->clk);
|
||||
|
|
@ -342,8 +337,7 @@ static int meson_spifc_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
out_pm:
|
||||
pm_runtime_disable(spifc->dev);
|
||||
out_err:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -351,6 +345,7 @@ static void meson_spifc_remove(struct platform_device *pdev)
|
|||
{
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
|
|||
|
|
@ -99,7 +99,6 @@
|
|||
#define REG_IEN (0x0c)
|
||||
#define REG_STATUS (0x10)
|
||||
#define REG_DIRECT_ACCESS (0x14)
|
||||
#define REG_UPPER_ACCESS (0x18)
|
||||
#define REG_RX_DATA (0x40)
|
||||
#define REG_TX_DATA (0x44)
|
||||
#define REG_X4_RX_DATA (0x48)
|
||||
|
|
@ -632,7 +631,7 @@ static int mchp_coreqspi_prepare_message(struct spi_controller *ctlr, struct spi
|
|||
ret = mchp_coreqspi_wait_for_ready(qspi);
|
||||
if (ret) {
|
||||
mutex_unlock(&qspi->op_lock);
|
||||
dev_err(&ctlr->dev, "Timeout waiting on QSPI ready.\n");
|
||||
dev_err(&m->spi->dev, "Timeout waiting on QSPI ready.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -472,13 +472,15 @@ static int mpc52xx_spi_probe(struct platform_device *op)
|
|||
if (ms->irq0 && ms->irq1) {
|
||||
rc = request_irq(ms->irq0, mpc52xx_spi_irq, 0,
|
||||
"mpc5200-spi-modf", ms);
|
||||
rc |= request_irq(ms->irq1, mpc52xx_spi_irq, 0,
|
||||
"mpc5200-spi-spif", ms);
|
||||
if (rc) {
|
||||
free_irq(ms->irq0, ms);
|
||||
free_irq(ms->irq1, ms);
|
||||
ms->irq0 = ms->irq1 = 0;
|
||||
if (rc == 0) {
|
||||
rc = request_irq(ms->irq1, mpc52xx_spi_irq, 0,
|
||||
"mpc5200-spi-spif", ms);
|
||||
if (rc)
|
||||
free_irq(ms->irq0, ms);
|
||||
}
|
||||
|
||||
if (rc)
|
||||
ms->irq0 = ms->irq1 = 0;
|
||||
} else {
|
||||
/* operate in polled mode */
|
||||
ms->irq0 = ms->irq1 = 0;
|
||||
|
|
@ -498,8 +500,10 @@ static int mpc52xx_spi_probe(struct platform_device *op)
|
|||
|
||||
err_register:
|
||||
dev_err(&ms->host->dev, "initialization failed\n");
|
||||
free_irq(ms->irq0, ms);
|
||||
free_irq(ms->irq1, ms);
|
||||
if (ms->irq0) {
|
||||
free_irq(ms->irq0, ms);
|
||||
free_irq(ms->irq1, ms);
|
||||
}
|
||||
cancel_work_sync(&ms->work);
|
||||
err_gpio:
|
||||
while (i-- > 0)
|
||||
|
|
@ -516,14 +520,16 @@ static int mpc52xx_spi_probe(struct platform_device *op)
|
|||
|
||||
static void mpc52xx_spi_remove(struct platform_device *op)
|
||||
{
|
||||
struct spi_controller *host = spi_controller_get(platform_get_drvdata(op));
|
||||
struct spi_controller *host = platform_get_drvdata(op);
|
||||
struct mpc52xx_spi *ms = spi_controller_get_devdata(host);
|
||||
int i;
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
free_irq(ms->irq0, ms);
|
||||
free_irq(ms->irq1, ms);
|
||||
if (ms->irq0) {
|
||||
free_irq(ms->irq0, ms);
|
||||
free_irq(ms->irq1, ms);
|
||||
}
|
||||
|
||||
cancel_work_sync(&ms->work);
|
||||
|
||||
|
|
|
|||
|
|
@ -127,9 +127,8 @@ static int spi_mux_probe(struct spi_device *spi)
|
|||
{
|
||||
struct spi_controller *ctlr;
|
||||
struct spi_mux_priv *priv;
|
||||
int ret;
|
||||
|
||||
ctlr = spi_alloc_host(&spi->dev, sizeof(*priv));
|
||||
ctlr = devm_spi_alloc_host(&spi->dev, sizeof(*priv));
|
||||
if (!ctlr)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -146,9 +145,8 @@ static int spi_mux_probe(struct spi_device *spi)
|
|||
|
||||
priv->mux = devm_mux_control_get(&spi->dev, NULL);
|
||||
if (IS_ERR(priv->mux)) {
|
||||
ret = dev_err_probe(&spi->dev, PTR_ERR(priv->mux),
|
||||
"failed to get control-mux\n");
|
||||
goto err_put_ctlr;
|
||||
return dev_err_probe(&spi->dev, PTR_ERR(priv->mux),
|
||||
"failed to get control-mux\n");
|
||||
}
|
||||
|
||||
priv->current_cs = SPI_MUX_NO_CS;
|
||||
|
|
@ -164,16 +162,7 @@ static int spi_mux_probe(struct spi_device *spi)
|
|||
ctlr->must_async = true;
|
||||
ctlr->defer_optimize_message = true;
|
||||
|
||||
ret = devm_spi_register_controller(&spi->dev, ctlr);
|
||||
if (ret)
|
||||
goto err_put_ctlr;
|
||||
|
||||
return 0;
|
||||
|
||||
err_put_ctlr:
|
||||
spi_controller_put(ctlr);
|
||||
|
||||
return ret;
|
||||
return devm_spi_register_controller(&spi->dev, ctlr);
|
||||
}
|
||||
|
||||
static const struct spi_device_id spi_mux_id[] = {
|
||||
|
|
|
|||
|
|
@ -403,20 +403,20 @@ static ssize_t mxic_spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
|||
if (WARN_ON(offs + desc->info.offset + len > U32_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
writel(mxic_spi_prep_hc_cfg(desc->mem->spi, 0, desc->info.op_tmpl.data.swap16),
|
||||
writel(mxic_spi_prep_hc_cfg(desc->mem->spi, 0, desc->info.op_tmpl->data.swap16),
|
||||
mxic->regs + HC_CFG);
|
||||
|
||||
writel(mxic_spi_mem_prep_op_cfg(&desc->info.op_tmpl, len),
|
||||
writel(mxic_spi_mem_prep_op_cfg(desc->info.op_tmpl, len),
|
||||
mxic->regs + LRD_CFG);
|
||||
writel(desc->info.offset + offs, mxic->regs + LRD_ADDR);
|
||||
len = min_t(size_t, len, mxic->linear.size);
|
||||
writel(len, mxic->regs + LRD_RANGE);
|
||||
writel(LMODE_CMD0(desc->info.op_tmpl.cmd.opcode) |
|
||||
writel(LMODE_CMD0(desc->info.op_tmpl->cmd.opcode) |
|
||||
LMODE_SLV_ACT(spi_get_chipselect(desc->mem->spi, 0)) |
|
||||
LMODE_EN,
|
||||
mxic->regs + LRD_CTRL);
|
||||
|
||||
if (mxic->ecc.use_pipelined_conf && desc->info.op_tmpl.data.ecc) {
|
||||
if (mxic->ecc.use_pipelined_conf && desc->info.op_tmpl->data.ecc) {
|
||||
ret = mxic_ecc_process_data_pipelined(mxic->ecc.pipelined_engine,
|
||||
NAND_PAGE_READ,
|
||||
mxic->linear.dma + offs);
|
||||
|
|
@ -448,20 +448,20 @@ static ssize_t mxic_spi_mem_dirmap_write(struct spi_mem_dirmap_desc *desc,
|
|||
if (WARN_ON(offs + desc->info.offset + len > U32_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
writel(mxic_spi_prep_hc_cfg(desc->mem->spi, 0, desc->info.op_tmpl.data.swap16),
|
||||
writel(mxic_spi_prep_hc_cfg(desc->mem->spi, 0, desc->info.op_tmpl->data.swap16),
|
||||
mxic->regs + HC_CFG);
|
||||
|
||||
writel(mxic_spi_mem_prep_op_cfg(&desc->info.op_tmpl, len),
|
||||
writel(mxic_spi_mem_prep_op_cfg(desc->info.op_tmpl, len),
|
||||
mxic->regs + LWR_CFG);
|
||||
writel(desc->info.offset + offs, mxic->regs + LWR_ADDR);
|
||||
len = min_t(size_t, len, mxic->linear.size);
|
||||
writel(len, mxic->regs + LWR_RANGE);
|
||||
writel(LMODE_CMD0(desc->info.op_tmpl.cmd.opcode) |
|
||||
writel(LMODE_CMD0(desc->info.op_tmpl->cmd.opcode) |
|
||||
LMODE_SLV_ACT(spi_get_chipselect(desc->mem->spi, 0)) |
|
||||
LMODE_EN,
|
||||
mxic->regs + LWR_CTRL);
|
||||
|
||||
if (mxic->ecc.use_pipelined_conf && desc->info.op_tmpl.data.ecc) {
|
||||
if (mxic->ecc.use_pipelined_conf && desc->info.op_tmpl->data.ecc) {
|
||||
ret = mxic_ecc_process_data_pipelined(mxic->ecc.pipelined_engine,
|
||||
NAND_PAGE_WRITE,
|
||||
mxic->linear.dma + offs);
|
||||
|
|
@ -509,7 +509,7 @@ static int mxic_spi_mem_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
|||
if (desc->info.offset + desc->info.length > U32_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
if (!mxic_spi_mem_supports_op(desc->mem, &desc->info.op_tmpl))
|
||||
if (!mxic_spi_mem_supports_op(desc->mem, desc->info.op_tmpl))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -563,7 +563,7 @@ static int mxs_spi_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
clk_freq = clk_freq_default;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*spi));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*spi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -589,13 +589,12 @@ static int mxs_spi_probe(struct platform_device *pdev)
|
|||
ret = devm_request_irq(&pdev->dev, irq_err, mxs_ssp_irq_handler, 0,
|
||||
dev_name(&pdev->dev), ssp);
|
||||
if (ret)
|
||||
goto out_host_free;
|
||||
return ret;
|
||||
|
||||
ssp->dmach = dma_request_chan(&pdev->dev, "rx-tx");
|
||||
if (IS_ERR(ssp->dmach)) {
|
||||
dev_err(ssp->dev, "Failed to request DMA\n");
|
||||
ret = PTR_ERR(ssp->dmach);
|
||||
goto out_host_free;
|
||||
return PTR_ERR(ssp->dmach);
|
||||
}
|
||||
|
||||
pm_runtime_enable(ssp->dev);
|
||||
|
|
@ -635,8 +634,7 @@ static int mxs_spi_probe(struct platform_device *pdev)
|
|||
pm_runtime_disable(ssp->dev);
|
||||
out_dma_release:
|
||||
dma_release_channel(ssp->dmach);
|
||||
out_host_free:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -650,8 +648,6 @@ static void mxs_spi_remove(struct platform_device *pdev)
|
|||
spi = spi_controller_get_devdata(host);
|
||||
ssp = &spi->ssp;
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
|
@ -659,8 +655,6 @@ static void mxs_spi_remove(struct platform_device *pdev)
|
|||
mxs_spi_runtime_suspend(&pdev->dev);
|
||||
|
||||
dma_release_channel(ssp->dmach);
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
static struct platform_driver mxs_spi_driver = {
|
||||
|
|
|
|||
|
|
@ -299,11 +299,11 @@ static ssize_t npcm_fiu_direct_read(struct spi_mem_dirmap_desc *desc,
|
|||
for (i = 0 ; i < len ; i++)
|
||||
*(buf_rx + i) = ioread8(src + i);
|
||||
} else {
|
||||
if (desc->info.op_tmpl.addr.buswidth != fiu->drd_op.addr.buswidth ||
|
||||
desc->info.op_tmpl.dummy.nbytes != fiu->drd_op.dummy.nbytes ||
|
||||
desc->info.op_tmpl.cmd.opcode != fiu->drd_op.cmd.opcode ||
|
||||
desc->info.op_tmpl.addr.nbytes != fiu->drd_op.addr.nbytes)
|
||||
npcm_fiu_set_drd(fiu, &desc->info.op_tmpl);
|
||||
if (desc->info.op_tmpl->addr.buswidth != fiu->drd_op.addr.buswidth ||
|
||||
desc->info.op_tmpl->dummy.nbytes != fiu->drd_op.dummy.nbytes ||
|
||||
desc->info.op_tmpl->cmd.opcode != fiu->drd_op.cmd.opcode ||
|
||||
desc->info.op_tmpl->addr.nbytes != fiu->drd_op.addr.nbytes)
|
||||
npcm_fiu_set_drd(fiu, desc->info.op_tmpl);
|
||||
|
||||
memcpy_fromio(buf_rx, src, len);
|
||||
}
|
||||
|
|
@ -609,7 +609,7 @@ static int npcm_fiu_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
|||
}
|
||||
|
||||
if (!fiu->spix_mode &&
|
||||
desc->info.op_tmpl.data.dir == SPI_MEM_DATA_OUT) {
|
||||
desc->info.op_tmpl->data.dir == SPI_MEM_DATA_OUT) {
|
||||
desc->nodirmap = true;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -644,9 +644,9 @@ static int npcm_fiu_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
|||
NPCM_FIU_CFG_FIU_FIX);
|
||||
}
|
||||
|
||||
if (desc->info.op_tmpl.data.dir == SPI_MEM_DATA_IN) {
|
||||
if (desc->info.op_tmpl->data.dir == SPI_MEM_DATA_IN) {
|
||||
if (!fiu->spix_mode)
|
||||
npcm_fiu_set_drd(fiu, &desc->info.op_tmpl);
|
||||
npcm_fiu_set_drd(fiu, desc->info.op_tmpl);
|
||||
else
|
||||
npcm_fiux_set_direct_rd(fiu);
|
||||
|
||||
|
|
|
|||
|
|
@ -345,7 +345,7 @@ static int npcm_pspi_probe(struct platform_device *pdev)
|
|||
int irq;
|
||||
int ret;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*priv));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*priv));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -356,21 +356,18 @@ static int npcm_pspi_probe(struct platform_device *pdev)
|
|||
priv->is_save_param = false;
|
||||
|
||||
priv->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(priv->base)) {
|
||||
ret = PTR_ERR(priv->base);
|
||||
goto out_host_put;
|
||||
}
|
||||
if (IS_ERR(priv->base))
|
||||
return PTR_ERR(priv->base);
|
||||
|
||||
priv->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(priv->clk)) {
|
||||
dev_err(&pdev->dev, "failed to get clock\n");
|
||||
ret = PTR_ERR(priv->clk);
|
||||
goto out_host_put;
|
||||
return PTR_ERR(priv->clk);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(priv->clk);
|
||||
if (ret)
|
||||
goto out_host_put;
|
||||
return ret;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
|
|
@ -424,8 +421,6 @@ static int npcm_pspi_probe(struct platform_device *pdev)
|
|||
out_disable_clk:
|
||||
clk_disable_unprepare(priv->clk);
|
||||
|
||||
out_host_put:
|
||||
spi_controller_put(host);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -434,14 +429,10 @@ static void npcm_pspi_remove(struct platform_device *pdev)
|
|||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct npcm_pspi *priv = spi_controller_get_devdata(host);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
npcm_pspi_reset_hw(priv);
|
||||
clk_disable_unprepare(priv->clk);
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
static const struct of_device_id npcm_pspi_match[] = {
|
||||
|
|
|
|||
|
|
@ -493,9 +493,8 @@ static void nxp_xspi_disable_ddr(struct nxp_xspi *xspi)
|
|||
writel(reg, base + XSPI_MCR);
|
||||
|
||||
reg &= ~XSPI_MCR_DDR_EN;
|
||||
reg &= ~XSPI_MCR_DQS_FA_SEL_MASK;
|
||||
/* Use dummy pad loopback mode to sample data */
|
||||
reg |= FIELD_PREP(XSPI_MCR_DQS_FA_SEL_MASK, 0x01);
|
||||
FIELD_MODIFY(XSPI_MCR_DQS_FA_SEL_MASK, ®, 0x01);
|
||||
writel(reg, base + XSPI_MCR);
|
||||
xspi->support_max_rate = 133000000;
|
||||
|
||||
|
|
@ -524,15 +523,13 @@ static void nxp_xspi_enable_ddr(struct nxp_xspi *xspi)
|
|||
writel(reg, base + XSPI_MCR);
|
||||
|
||||
reg |= XSPI_MCR_DDR_EN;
|
||||
reg &= ~XSPI_MCR_DQS_FA_SEL_MASK;
|
||||
/* Use external dqs to sample data */
|
||||
reg |= FIELD_PREP(XSPI_MCR_DQS_FA_SEL_MASK, 0x03);
|
||||
FIELD_MODIFY(XSPI_MCR_DQS_FA_SEL_MASK, ®, 0x03);
|
||||
writel(reg, base + XSPI_MCR);
|
||||
xspi->support_max_rate = 200000000;
|
||||
|
||||
reg = readl(base + XSPI_FLSHCR);
|
||||
reg &= ~XSPI_FLSHCR_TDH_MASK;
|
||||
reg |= FIELD_PREP(XSPI_FLSHCR_TDH_MASK, 0x01);
|
||||
FIELD_MODIFY(XSPI_FLSHCR_TDH_MASK, ®, 0x01);
|
||||
writel(reg, base + XSPI_FLSHCR);
|
||||
|
||||
reg = FIELD_PREP(XSPI_SMPR_DLLFSMPFA_MASK, 0x04);
|
||||
|
|
@ -1096,8 +1093,7 @@ static int nxp_xspi_default_setup(struct nxp_xspi *xspi)
|
|||
|
||||
/* Give read/write access right to EENV0 */
|
||||
reg = readl(base + XSPI_FRAD0_WORD2);
|
||||
reg &= ~XSPI_FRAD0_WORD2_MD0ACP_MASK;
|
||||
reg |= FIELD_PREP(XSPI_FRAD0_WORD2_MD0ACP_MASK, 0x03);
|
||||
FIELD_MODIFY(XSPI_FRAD0_WORD2_MD0ACP_MASK, ®, 0x03);
|
||||
writel(reg, base + XSPI_FRAD0_WORD2);
|
||||
|
||||
/* Enable the FRAD check for EENV0 */
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/gcd.h>
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
|
|
@ -1481,12 +1480,11 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
|
|||
int status = 0, i;
|
||||
u32 regs_offset = 0;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
const struct of_device_id *match;
|
||||
|
||||
if (of_property_read_bool(node, "spi-slave"))
|
||||
ctlr = spi_alloc_target(&pdev->dev, sizeof(*mcspi));
|
||||
ctlr = devm_spi_alloc_target(&pdev->dev, sizeof(*mcspi));
|
||||
else
|
||||
ctlr = spi_alloc_host(&pdev->dev, sizeof(*mcspi));
|
||||
ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*mcspi));
|
||||
if (!ctlr)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -1509,10 +1507,9 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
|
|||
mcspi = spi_controller_get_devdata(ctlr);
|
||||
mcspi->ctlr = ctlr;
|
||||
|
||||
match = of_match_device(omap_mcspi_of_match, &pdev->dev);
|
||||
if (match) {
|
||||
pdata = of_device_get_match_data(&pdev->dev);
|
||||
if (pdata) {
|
||||
u32 num_cs = 1; /* default number of chipselect */
|
||||
pdata = match->data;
|
||||
|
||||
of_property_read_u32(node, "ti,spi-num-cs", &num_cs);
|
||||
ctlr->num_chipselect = num_cs;
|
||||
|
|
@ -1530,10 +1527,9 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
mcspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r);
|
||||
if (IS_ERR(mcspi->base)) {
|
||||
status = PTR_ERR(mcspi->base);
|
||||
goto free_ctlr;
|
||||
}
|
||||
if (IS_ERR(mcspi->base))
|
||||
return PTR_ERR(mcspi->base);
|
||||
|
||||
mcspi->phys = r->start + regs_offset;
|
||||
mcspi->base += regs_offset;
|
||||
|
||||
|
|
@ -1544,10 +1540,8 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
|
|||
mcspi->dma_channels = devm_kcalloc(&pdev->dev, ctlr->num_chipselect,
|
||||
sizeof(struct omap2_mcspi_dma),
|
||||
GFP_KERNEL);
|
||||
if (mcspi->dma_channels == NULL) {
|
||||
status = -ENOMEM;
|
||||
goto free_ctlr;
|
||||
}
|
||||
if (mcspi->dma_channels == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < ctlr->num_chipselect; i++) {
|
||||
sprintf(mcspi->dma_channels[i].dma_rx_ch_name, "rx%d", i);
|
||||
|
|
@ -1556,26 +1550,27 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
|
|||
status = omap2_mcspi_request_dma(mcspi,
|
||||
&mcspi->dma_channels[i]);
|
||||
if (status == -EPROBE_DEFER)
|
||||
goto free_ctlr;
|
||||
goto err_release_dma;
|
||||
}
|
||||
|
||||
status = platform_get_irq(pdev, 0);
|
||||
if (status < 0)
|
||||
goto free_ctlr;
|
||||
goto err_release_dma;
|
||||
|
||||
init_completion(&mcspi->txdone);
|
||||
status = devm_request_irq(&pdev->dev, status,
|
||||
omap2_mcspi_irq_handler, 0, pdev->name,
|
||||
mcspi);
|
||||
if (status) {
|
||||
dev_err(&pdev->dev, "Cannot request IRQ");
|
||||
goto free_ctlr;
|
||||
goto err_release_dma;
|
||||
}
|
||||
|
||||
mcspi->ref_clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(mcspi->ref_clk)) {
|
||||
status = PTR_ERR(mcspi->ref_clk);
|
||||
dev_err_probe(&pdev->dev, status, "Failed to get ref_clk");
|
||||
goto free_ctlr;
|
||||
goto err_release_dma;
|
||||
}
|
||||
if (mcspi->ref_clk)
|
||||
mcspi->ref_clk_hz = clk_get_rate(mcspi->ref_clk);
|
||||
|
|
@ -1590,21 +1585,21 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
|
|||
|
||||
status = omap2_mcspi_controller_setup(mcspi);
|
||||
if (status < 0)
|
||||
goto disable_pm;
|
||||
goto err_disable_rpm;
|
||||
|
||||
status = spi_register_controller(ctlr);
|
||||
if (status < 0)
|
||||
goto disable_pm;
|
||||
goto err_disable_rpm;
|
||||
|
||||
return status;
|
||||
return 0;
|
||||
|
||||
disable_pm:
|
||||
err_disable_rpm:
|
||||
pm_runtime_dont_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_put_sync(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
free_ctlr:
|
||||
err_release_dma:
|
||||
omap2_mcspi_release_dma(ctlr);
|
||||
spi_controller_put(ctlr);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -1613,8 +1608,6 @@ static void omap2_mcspi_remove(struct platform_device *pdev)
|
|||
struct spi_controller *ctlr = platform_get_drvdata(pdev);
|
||||
struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr);
|
||||
|
||||
spi_controller_get(ctlr);
|
||||
|
||||
spi_unregister_controller(ctlr);
|
||||
|
||||
omap2_mcspi_release_dma(ctlr);
|
||||
|
|
@ -1622,8 +1615,6 @@ static void omap2_mcspi_remove(struct platform_device *pdev)
|
|||
pm_runtime_dont_use_autosuspend(mcspi->dev);
|
||||
pm_runtime_put_sync(mcspi->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
spi_controller_put(ctlr);
|
||||
}
|
||||
|
||||
/* work with hotplug and coldplug */
|
||||
|
|
|
|||
|
|
@ -651,11 +651,9 @@ static int orion_spi_probe(struct platform_device *pdev)
|
|||
struct device_node *np;
|
||||
int status;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*spi));
|
||||
if (host == NULL) {
|
||||
dev_dbg(&pdev->dev, "host allocation failed\n");
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*spi));
|
||||
if (host == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (pdev->id != -1)
|
||||
host->bus_num = pdev->id;
|
||||
|
|
@ -689,17 +687,14 @@ static int orion_spi_probe(struct platform_device *pdev)
|
|||
spi->devdata = devdata;
|
||||
|
||||
spi->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(spi->clk)) {
|
||||
status = PTR_ERR(spi->clk);
|
||||
goto out;
|
||||
}
|
||||
if (IS_ERR(spi->clk))
|
||||
return PTR_ERR(spi->clk);
|
||||
|
||||
/* The following clock is only used by some SoCs */
|
||||
spi->axi_clk = devm_clk_get(&pdev->dev, "axi");
|
||||
if (PTR_ERR(spi->axi_clk) == -EPROBE_DEFER) {
|
||||
status = -EPROBE_DEFER;
|
||||
goto out;
|
||||
}
|
||||
if (PTR_ERR(spi->axi_clk) == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
if (!IS_ERR(spi->axi_clk))
|
||||
clk_prepare_enable(spi->axi_clk);
|
||||
|
||||
|
|
@ -796,8 +791,7 @@ static int orion_spi_probe(struct platform_device *pdev)
|
|||
pm_runtime_dont_use_autosuspend(&pdev->dev);
|
||||
out_rel_axi_clk:
|
||||
clk_disable_unprepare(spi->axi_clk);
|
||||
out:
|
||||
spi_controller_put(host);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -807,15 +801,11 @@ static void orion_spi_remove(struct platform_device *pdev)
|
|||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct orion_spi *spi = spi_controller_get_devdata(host);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
clk_disable_unprepare(spi->axi_clk);
|
||||
|
||||
spi_controller_put(host);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
|
|
|
|||
|
|
@ -173,27 +173,27 @@ struct pci1xxxx_spi {
|
|||
};
|
||||
|
||||
static const struct pci_device_id pci1xxxx_spi_pci_id_table[] = {
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa004, PCI_ANY_ID, 0x0001), 0, 0, 0x02},
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa004, PCI_ANY_ID, 0x0002), 0, 0, 0x01},
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa004, PCI_ANY_ID, 0x0003), 0, 0, 0x11},
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa004, PCI_ANY_ID, PCI_ANY_ID), 0, 0, 0x01},
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa014, PCI_ANY_ID, 0x0001), 0, 0, 0x02},
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa014, PCI_ANY_ID, 0x0002), 0, 0, 0x01},
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa014, PCI_ANY_ID, 0x0003), 0, 0, 0x11},
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa014, PCI_ANY_ID, PCI_ANY_ID), 0, 0, 0x01},
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa024, PCI_ANY_ID, 0x0001), 0, 0, 0x02},
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa024, PCI_ANY_ID, 0x0002), 0, 0, 0x01},
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa024, PCI_ANY_ID, 0x0003), 0, 0, 0x11},
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa024, PCI_ANY_ID, PCI_ANY_ID), 0, 0, 0x01},
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa034, PCI_ANY_ID, 0x0001), 0, 0, 0x02},
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa034, PCI_ANY_ID, 0x0002), 0, 0, 0x01},
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa034, PCI_ANY_ID, 0x0003), 0, 0, 0x11},
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa034, PCI_ANY_ID, PCI_ANY_ID), 0, 0, 0x01},
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa044, PCI_ANY_ID, 0x0001), 0, 0, 0x02},
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa044, PCI_ANY_ID, 0x0002), 0, 0, 0x01},
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa044, PCI_ANY_ID, 0x0003), 0, 0, 0x11},
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa044, PCI_ANY_ID, PCI_ANY_ID), 0, 0, 0x01},
|
||||
{ 0, }
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa004, PCI_ANY_ID, 0x0001), .driver_data = 0x02 },
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa004, PCI_ANY_ID, 0x0002), .driver_data = 0x01 },
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa004, PCI_ANY_ID, 0x0003), .driver_data = 0x11 },
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa004, PCI_ANY_ID, PCI_ANY_ID), .driver_data = 0x01 },
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa014, PCI_ANY_ID, 0x0001), .driver_data = 0x02 },
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa014, PCI_ANY_ID, 0x0002), .driver_data = 0x01 },
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa014, PCI_ANY_ID, 0x0003), .driver_data = 0x11 },
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa014, PCI_ANY_ID, PCI_ANY_ID), .driver_data = 0x01 },
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa024, PCI_ANY_ID, 0x0001), .driver_data = 0x02 },
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa024, PCI_ANY_ID, 0x0002), .driver_data = 0x01 },
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa024, PCI_ANY_ID, 0x0003), .driver_data = 0x11 },
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa024, PCI_ANY_ID, PCI_ANY_ID), .driver_data = 0x01 },
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa034, PCI_ANY_ID, 0x0001), .driver_data = 0x02 },
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa034, PCI_ANY_ID, 0x0002), .driver_data = 0x01 },
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa034, PCI_ANY_ID, 0x0003), .driver_data = 0x11 },
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa034, PCI_ANY_ID, PCI_ANY_ID), .driver_data = 0x01 },
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa044, PCI_ANY_ID, 0x0001), .driver_data = 0x02 },
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa044, PCI_ANY_ID, 0x0002), .driver_data = 0x01 },
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa044, PCI_ANY_ID, 0x0003), .driver_data = 0x11 },
|
||||
{ PCI_DEVICE_SUB(VENDOR_ID_MCHP, 0xa044, PCI_ANY_ID, PCI_ANY_ID), .driver_data = 0x01 },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, pci1xxxx_spi_pci_id_table);
|
||||
|
|
|
|||
|
|
@ -572,7 +572,7 @@ static int pic32_sqi_probe(struct platform_device *pdev)
|
|||
struct pic32_sqi *sqi;
|
||||
int ret;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*sqi));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*sqi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -580,31 +580,25 @@ static int pic32_sqi_probe(struct platform_device *pdev)
|
|||
sqi->host = host;
|
||||
|
||||
sqi->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(sqi->regs)) {
|
||||
ret = PTR_ERR(sqi->regs);
|
||||
goto err_free_host;
|
||||
}
|
||||
if (IS_ERR(sqi->regs))
|
||||
return PTR_ERR(sqi->regs);
|
||||
|
||||
/* irq */
|
||||
sqi->irq = platform_get_irq(pdev, 0);
|
||||
if (sqi->irq < 0) {
|
||||
ret = sqi->irq;
|
||||
goto err_free_host;
|
||||
}
|
||||
if (sqi->irq < 0)
|
||||
return sqi->irq;
|
||||
|
||||
/* clocks */
|
||||
sqi->sys_clk = devm_clk_get_enabled(&pdev->dev, "reg_ck");
|
||||
if (IS_ERR(sqi->sys_clk)) {
|
||||
ret = PTR_ERR(sqi->sys_clk);
|
||||
dev_err(&pdev->dev, "no sys_clk ?\n");
|
||||
goto err_free_host;
|
||||
return PTR_ERR(sqi->sys_clk);
|
||||
}
|
||||
|
||||
sqi->base_clk = devm_clk_get_enabled(&pdev->dev, "spi_ck");
|
||||
if (IS_ERR(sqi->base_clk)) {
|
||||
ret = PTR_ERR(sqi->base_clk);
|
||||
dev_err(&pdev->dev, "no base clk ?\n");
|
||||
goto err_free_host;
|
||||
return PTR_ERR(sqi->base_clk);
|
||||
}
|
||||
|
||||
init_completion(&sqi->xfer_done);
|
||||
|
|
@ -616,7 +610,7 @@ static int pic32_sqi_probe(struct platform_device *pdev)
|
|||
ret = ring_desc_ring_alloc(sqi);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "ring alloc failed\n");
|
||||
goto err_free_host;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* install irq handlers */
|
||||
|
|
@ -656,8 +650,6 @@ static int pic32_sqi_probe(struct platform_device *pdev)
|
|||
err_free_ring:
|
||||
ring_desc_ring_free(sqi);
|
||||
|
||||
err_free_host:
|
||||
spi_controller_put(host);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -665,15 +657,11 @@ static void pic32_sqi_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct pic32_sqi *sqi = platform_get_drvdata(pdev);
|
||||
|
||||
spi_controller_get(sqi->host);
|
||||
|
||||
spi_unregister_controller(sqi->host);
|
||||
|
||||
/* release resources */
|
||||
free_irq(sqi->irq, sqi);
|
||||
ring_desc_ring_free(sqi);
|
||||
|
||||
spi_controller_put(sqi->host);
|
||||
}
|
||||
|
||||
static const struct of_device_id pic32_sqi_of_ids[] = {
|
||||
|
|
|
|||
|
|
@ -752,7 +752,7 @@ static int pic32_spi_probe(struct platform_device *pdev)
|
|||
struct pic32_spi *pic32s;
|
||||
int ret;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*pic32s));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*pic32s));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -761,7 +761,7 @@ static int pic32_spi_probe(struct platform_device *pdev)
|
|||
|
||||
ret = pic32_spi_hw_probe(pdev, pic32s);
|
||||
if (ret)
|
||||
goto err_host;
|
||||
return ret;
|
||||
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
host->mode_bits = SPI_MODE_3 | SPI_MODE_0 | SPI_CS_HIGH;
|
||||
|
|
@ -833,8 +833,7 @@ static int pic32_spi_probe(struct platform_device *pdev)
|
|||
|
||||
err_bailout:
|
||||
pic32_spi_dma_unprep(pic32s);
|
||||
err_host:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -842,14 +841,10 @@ static void pic32_spi_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct pic32_spi *pic32s = platform_get_drvdata(pdev);
|
||||
|
||||
spi_controller_get(pic32s->host);
|
||||
|
||||
spi_unregister_controller(pic32s->host);
|
||||
|
||||
pic32_spi_disable(pic32s);
|
||||
pic32_spi_dma_unprep(pic32s);
|
||||
|
||||
spi_controller_put(pic32s->host);
|
||||
}
|
||||
|
||||
static const struct of_device_id pic32_spi_of_match[] = {
|
||||
|
|
|
|||
|
|
@ -1868,7 +1868,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
}
|
||||
|
||||
/* Allocate host with space for data */
|
||||
host = spi_alloc_host(dev, sizeof(struct pl022));
|
||||
host = devm_spi_alloc_host(dev, sizeof(struct pl022));
|
||||
if (host == NULL) {
|
||||
dev_err(&adev->dev, "probe - cannot alloc SPI host\n");
|
||||
return -ENOMEM;
|
||||
|
|
@ -1907,7 +1907,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
|
||||
status = amba_request_regions(adev, NULL);
|
||||
if (status)
|
||||
goto err_no_ioregion;
|
||||
return status;
|
||||
|
||||
pl022->phybase = adev->res.start;
|
||||
pl022->virtbase = devm_ioremap(dev, adev->res.start,
|
||||
|
|
@ -1984,8 +1984,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
err_no_clk:
|
||||
err_no_ioremap:
|
||||
amba_release_regions(adev);
|
||||
err_no_ioregion:
|
||||
spi_controller_put(host);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -1997,8 +1996,6 @@ pl022_remove(struct amba_device *adev)
|
|||
if (!pl022)
|
||||
return;
|
||||
|
||||
spi_controller_get(pl022->host);
|
||||
|
||||
spi_unregister_controller(pl022->host);
|
||||
|
||||
/*
|
||||
|
|
@ -2012,8 +2009,6 @@ pl022_remove(struct amba_device *adev)
|
|||
pl022_dma_remove(pl022);
|
||||
|
||||
amba_release_regions(adev);
|
||||
|
||||
spi_controller_put(pl022->host);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
|
|||
|
|
@ -174,6 +174,7 @@ struct qcom_qspi {
|
|||
void *virt_cmd_desc[QSPI_MAX_SG];
|
||||
unsigned int n_cmd_desc;
|
||||
struct icc_path *icc_path_cpu_to_qspi;
|
||||
struct icc_path *icc_path_mem;
|
||||
unsigned long last_speed;
|
||||
/* Lock to protect data accessed by IRQs */
|
||||
spinlock_t lock;
|
||||
|
|
@ -272,7 +273,7 @@ static void qcom_qspi_handle_err(struct spi_controller *host,
|
|||
static int qcom_qspi_set_speed(struct qcom_qspi *ctrl, unsigned long speed_hz)
|
||||
{
|
||||
int ret;
|
||||
unsigned int avg_bw_cpu;
|
||||
unsigned int avg_bw_cpu, avg_bw_mem;
|
||||
|
||||
if (speed_hz == ctrl->last_speed)
|
||||
return 0;
|
||||
|
|
@ -285,7 +286,7 @@ static int qcom_qspi_set_speed(struct qcom_qspi *ctrl, unsigned long speed_hz)
|
|||
}
|
||||
|
||||
/*
|
||||
* Set BW quota for CPU.
|
||||
* Set BW quota for CPU and memory paths.
|
||||
* We don't have explicit peak requirement so keep it equal to avg_bw.
|
||||
*/
|
||||
avg_bw_cpu = Bps_to_icc(speed_hz);
|
||||
|
|
@ -296,6 +297,13 @@ static int qcom_qspi_set_speed(struct qcom_qspi *ctrl, unsigned long speed_hz)
|
|||
return ret;
|
||||
}
|
||||
|
||||
avg_bw_mem = Bps_to_icc(speed_hz);
|
||||
ret = icc_set_bw(ctrl->icc_path_mem, avg_bw_mem, avg_bw_mem);
|
||||
if (ret) {
|
||||
dev_err(ctrl->dev, "ICC BW voting failed for memory: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctrl->last_speed = speed_hz;
|
||||
|
||||
return 0;
|
||||
|
|
@ -729,6 +737,14 @@ static int qcom_qspi_probe(struct platform_device *pdev)
|
|||
return dev_err_probe(dev, PTR_ERR(ctrl->icc_path_cpu_to_qspi),
|
||||
"Failed to get cpu path\n");
|
||||
|
||||
ctrl->icc_path_mem = devm_of_icc_get(dev, "qspi-memory");
|
||||
if (IS_ERR(ctrl->icc_path_mem)) {
|
||||
if (PTR_ERR(ctrl->icc_path_mem) != -ENODATA)
|
||||
return dev_err_probe(dev, PTR_ERR(ctrl->icc_path_mem),
|
||||
"Failed to get memory path\n");
|
||||
ctrl->icc_path_mem = NULL;
|
||||
}
|
||||
|
||||
/* Set BW vote for register access */
|
||||
ret = icc_set_bw(ctrl->icc_path_cpu_to_qspi, Bps_to_icc(1000),
|
||||
Bps_to_icc(1000));
|
||||
|
|
@ -818,20 +834,42 @@ static int __maybe_unused qcom_qspi_runtime_suspend(struct device *dev)
|
|||
struct qcom_qspi *ctrl = spi_controller_get_devdata(host);
|
||||
int ret;
|
||||
|
||||
/* Drop the performance state vote */
|
||||
dev_pm_opp_set_rate(dev, 0);
|
||||
clk_bulk_disable_unprepare(QSPI_NUM_CLKS, ctrl->clks);
|
||||
|
||||
ret = icc_disable(ctrl->icc_path_cpu_to_qspi);
|
||||
if (ret) {
|
||||
dev_err_ratelimited(ctrl->dev, "%s: ICC disable failed for cpu: %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
goto err_enable_clk;
|
||||
}
|
||||
|
||||
pinctrl_pm_select_sleep_state(dev);
|
||||
ret = icc_disable(ctrl->icc_path_mem);
|
||||
if (ret) {
|
||||
dev_err_ratelimited(ctrl->dev, "ICC disable failed for memory: %d\n", ret);
|
||||
goto err_enable_icc_cpu;
|
||||
}
|
||||
|
||||
ret = pinctrl_pm_select_sleep_state(dev);
|
||||
if (ret)
|
||||
goto err_enable_icc_mem;
|
||||
|
||||
/* Drop the performance state vote */
|
||||
ret = dev_pm_opp_set_rate(dev, 0);
|
||||
if (ret)
|
||||
goto err_select_default_state;
|
||||
|
||||
return 0;
|
||||
|
||||
err_select_default_state:
|
||||
pinctrl_pm_select_default_state(dev);
|
||||
err_enable_icc_mem:
|
||||
icc_enable(ctrl->icc_path_mem);
|
||||
err_enable_icc_cpu:
|
||||
icc_enable(ctrl->icc_path_cpu_to_qspi);
|
||||
err_enable_clk:
|
||||
if (clk_bulk_prepare_enable(QSPI_NUM_CLKS, ctrl->clks))
|
||||
dev_err_ratelimited(ctrl->dev, "Failed to re-enable clocks\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __maybe_unused qcom_qspi_runtime_resume(struct device *dev)
|
||||
|
|
@ -840,20 +878,42 @@ static int __maybe_unused qcom_qspi_runtime_resume(struct device *dev)
|
|||
struct qcom_qspi *ctrl = spi_controller_get_devdata(host);
|
||||
int ret;
|
||||
|
||||
pinctrl_pm_select_default_state(dev);
|
||||
ret = dev_pm_opp_set_rate(dev, ctrl->last_speed * 4);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pinctrl_pm_select_default_state(dev);
|
||||
if (ret)
|
||||
goto err_opp_set_rate_zero;
|
||||
|
||||
ret = icc_enable(ctrl->icc_path_cpu_to_qspi);
|
||||
if (ret) {
|
||||
dev_err_ratelimited(ctrl->dev, "%s: ICC enable failed for cpu: %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
goto err_select_sleep_state;
|
||||
}
|
||||
|
||||
ret = icc_enable(ctrl->icc_path_mem);
|
||||
if (ret) {
|
||||
dev_err_ratelimited(ctrl->dev, "ICC enable failed for memory: %d\n", ret);
|
||||
goto err_disable_icc_cpu;
|
||||
}
|
||||
|
||||
ret = clk_bulk_prepare_enable(QSPI_NUM_CLKS, ctrl->clks);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_disable_icc_mem;
|
||||
|
||||
return dev_pm_opp_set_rate(dev, ctrl->last_speed * 4);
|
||||
return 0;
|
||||
|
||||
err_disable_icc_mem:
|
||||
icc_disable(ctrl->icc_path_mem);
|
||||
err_disable_icc_cpu:
|
||||
icc_disable(ctrl->icc_path_cpu_to_qspi);
|
||||
err_select_sleep_state:
|
||||
pinctrl_pm_select_sleep_state(dev);
|
||||
err_opp_set_rate_zero:
|
||||
dev_pm_opp_set_rate(dev, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __maybe_unused qcom_qspi_suspend(struct device *dev)
|
||||
|
|
|
|||
|
|
@ -1074,11 +1074,9 @@ static int spi_qup_probe(struct platform_device *pdev)
|
|||
if (ret && ret != -ENODEV)
|
||||
return dev_err_probe(dev, ret, "invalid OPP table\n");
|
||||
|
||||
host = spi_alloc_host(dev, sizeof(struct spi_qup));
|
||||
if (!host) {
|
||||
dev_err(dev, "cannot allocate host\n");
|
||||
host = devm_spi_alloc_host(dev, sizeof(struct spi_qup));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* use num-cs unless not present or out of range */
|
||||
if (of_property_read_u32(dev->of_node, "num-cs", &num_cs) ||
|
||||
|
|
@ -1111,7 +1109,7 @@ static int spi_qup_probe(struct platform_device *pdev)
|
|||
|
||||
ret = spi_qup_init_dma(host, res->start);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
goto error;
|
||||
return ret;
|
||||
else if (!ret)
|
||||
host->can_dma = spi_qup_can_dma;
|
||||
|
||||
|
|
@ -1209,8 +1207,7 @@ static int spi_qup_probe(struct platform_device *pdev)
|
|||
clk_disable_unprepare(iclk);
|
||||
error_dma:
|
||||
spi_qup_release_dma(host);
|
||||
error:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1323,8 +1320,6 @@ static void spi_qup_remove(struct platform_device *pdev)
|
|||
struct spi_qup *controller = spi_controller_get_devdata(host);
|
||||
int ret;
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
ret = pm_runtime_get_sync(&pdev->dev);
|
||||
|
|
@ -1346,8 +1341,6 @@ static void spi_qup_remove(struct platform_device *pdev)
|
|||
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
static const struct of_device_id spi_qup_dt_match[] = {
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ static ssize_t xspi_spi_mem_dirmap_write(struct spi_mem_dirmap_desc *desc,
|
|||
if (offs + desc->info.offset + len > U32_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
rpcif_spi_mem_prepare(desc->mem->spi, &desc->info.op_tmpl, &offs, &len);
|
||||
rpcif_spi_mem_prepare(desc->mem->spi, desc->info.op_tmpl, &offs, &len);
|
||||
|
||||
return xspi_dirmap_write(rpc->dev, offs, len, buf);
|
||||
}
|
||||
|
|
@ -97,7 +97,7 @@ static ssize_t rpcif_spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
|||
if (offs + desc->info.offset + len > U32_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
rpcif_spi_mem_prepare(desc->mem->spi, &desc->info.op_tmpl, &offs, &len);
|
||||
rpcif_spi_mem_prepare(desc->mem->spi, desc->info.op_tmpl, &offs, &len);
|
||||
|
||||
return rpcif_dirmap_read(rpc->dev, offs, len, buf);
|
||||
}
|
||||
|
|
@ -110,13 +110,13 @@ static int rpcif_spi_mem_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
|||
if (desc->info.offset + desc->info.length > U32_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
if (!rpcif_spi_mem_supports_op(desc->mem, &desc->info.op_tmpl))
|
||||
if (!rpcif_spi_mem_supports_op(desc->mem, desc->info.op_tmpl))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!rpc->dirmap)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!rpc->xspi && desc->info.op_tmpl.data.dir != SPI_MEM_DATA_IN)
|
||||
if (!rpc->xspi && desc->info.op_tmpl->data.dir != SPI_MEM_DATA_IN)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1171,14 +1171,10 @@ static void rspi_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct rspi_data *rspi = platform_get_drvdata(pdev);
|
||||
|
||||
spi_controller_get(rspi->ctlr);
|
||||
|
||||
spi_unregister_controller(rspi->ctlr);
|
||||
|
||||
rspi_release_dma(rspi->ctlr);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
spi_controller_put(rspi->ctlr);
|
||||
}
|
||||
|
||||
static const struct spi_ops rspi_ops = {
|
||||
|
|
@ -1226,11 +1222,6 @@ static const struct of_device_id rspi_of_match[] __maybe_unused = {
|
|||
MODULE_DEVICE_TABLE(of, rspi_of_match);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static void rspi_reset_control_assert(void *data)
|
||||
{
|
||||
reset_control_assert(data);
|
||||
}
|
||||
|
||||
static int rspi_parse_dt(struct device *dev, struct spi_controller *ctlr)
|
||||
{
|
||||
struct reset_control *rstc;
|
||||
|
|
@ -1246,22 +1237,10 @@ static int rspi_parse_dt(struct device *dev, struct spi_controller *ctlr)
|
|||
|
||||
ctlr->num_chipselect = num_cs;
|
||||
|
||||
rstc = devm_reset_control_get_optional_exclusive(dev, NULL);
|
||||
rstc = devm_reset_control_get_optional_exclusive_deasserted(dev, NULL);
|
||||
if (IS_ERR(rstc))
|
||||
return dev_err_probe(dev, PTR_ERR(rstc),
|
||||
"failed to get reset ctrl\n");
|
||||
|
||||
error = reset_control_deassert(rstc);
|
||||
if (error) {
|
||||
dev_err(dev, "failed to deassert reset %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = devm_add_action_or_reset(dev, rspi_reset_control_assert, rstc);
|
||||
if (error) {
|
||||
dev_err(dev, "failed to register assert devm action, %d\n", error);
|
||||
return error;
|
||||
}
|
||||
"failed to get reset ctrl and deassert reset\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1294,7 +1273,7 @@ static int rspi_probe(struct platform_device *pdev)
|
|||
const struct spi_ops *ops;
|
||||
unsigned long clksrc;
|
||||
|
||||
ctlr = spi_alloc_host(&pdev->dev, sizeof(struct rspi_data));
|
||||
ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(struct rspi_data));
|
||||
if (ctlr == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -1302,7 +1281,7 @@ static int rspi_probe(struct platform_device *pdev)
|
|||
if (ops) {
|
||||
ret = rspi_parse_dt(&pdev->dev, ctlr);
|
||||
if (ret)
|
||||
goto error1;
|
||||
return ret;
|
||||
} else {
|
||||
ops = (struct spi_ops *)pdev->id_entry->driver_data;
|
||||
ctlr->num_chipselect = 2; /* default */
|
||||
|
|
@ -1314,16 +1293,13 @@ static int rspi_probe(struct platform_device *pdev)
|
|||
rspi->ctlr = ctlr;
|
||||
|
||||
rspi->addr = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
if (IS_ERR(rspi->addr)) {
|
||||
ret = PTR_ERR(rspi->addr);
|
||||
goto error1;
|
||||
}
|
||||
if (IS_ERR(rspi->addr))
|
||||
return PTR_ERR(rspi->addr);
|
||||
|
||||
rspi->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(rspi->clk)) {
|
||||
dev_err(&pdev->dev, "cannot get clock\n");
|
||||
ret = PTR_ERR(rspi->clk);
|
||||
goto error1;
|
||||
return PTR_ERR(rspi->clk);
|
||||
}
|
||||
|
||||
rspi->pdev = pdev;
|
||||
|
|
@ -1396,15 +1372,13 @@ static int rspi_probe(struct platform_device *pdev)
|
|||
rspi_release_dma(ctlr);
|
||||
error2:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
error1:
|
||||
spi_controller_put(ctlr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct platform_device_id spi_driver_ids[] = {
|
||||
{ "rspi", (kernel_ulong_t)&rspi_ops },
|
||||
{},
|
||||
{ .name = "rspi", .driver_data = (kernel_ulong_t)&rspi_ops },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(platform, spi_driver_ids);
|
||||
|
|
|
|||
|
|
@ -803,6 +803,23 @@ static int rzv2h_rspi_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int rzv2h_rspi_suspend(struct device *dev)
|
||||
{
|
||||
struct rzv2h_rspi_priv *rspi = dev_get_drvdata(dev);
|
||||
|
||||
return spi_controller_suspend(rspi->controller);
|
||||
}
|
||||
|
||||
static int rzv2h_rspi_resume(struct device *dev)
|
||||
{
|
||||
struct rzv2h_rspi_priv *rspi = dev_get_drvdata(dev);
|
||||
|
||||
return spi_controller_resume(rspi->controller);
|
||||
}
|
||||
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(rzv2h_rspi_pm_ops, rzv2h_rspi_suspend,
|
||||
rzv2h_rspi_resume);
|
||||
|
||||
static const struct rzv2h_rspi_info rzv2h_info = {
|
||||
.find_tclk_rate = rzv2h_rspi_find_rate_fixed,
|
||||
.tclk_name = "tclk",
|
||||
|
|
@ -838,6 +855,7 @@ static struct platform_driver rzv2h_rspi_drv = {
|
|||
.driver = {
|
||||
.name = "rzv2h_rspi",
|
||||
.of_match_table = rzv2h_rspi_match,
|
||||
.pm = pm_sleep_ptr(&rzv2h_rspi_pm_ops),
|
||||
},
|
||||
};
|
||||
module_platform_driver(rzv2h_rspi_drv);
|
||||
|
|
|
|||
|
|
@ -1613,10 +1613,10 @@ static const struct s3c64xx_spi_port_config gs101_spi_port_config = {
|
|||
|
||||
static const struct platform_device_id s3c64xx_spi_driver_ids[] = {
|
||||
{
|
||||
.name = "s3c6410-spi",
|
||||
.driver_data = (kernel_ulong_t)&s3c6410_spi_port_config,
|
||||
.name = "s3c6410-spi",
|
||||
.driver_data = (kernel_ulong_t)&s3c6410_spi_port_config,
|
||||
},
|
||||
{ },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, s3c64xx_spi_driver_ids);
|
||||
|
||||
|
|
|
|||
|
|
@ -295,9 +295,9 @@ static int sc18is602_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id sc18is602_id[] = {
|
||||
{ "sc18is602", sc18is602 },
|
||||
{ "sc18is602b", sc18is602b },
|
||||
{ "sc18is603", sc18is603 },
|
||||
{ .name = "sc18is602", .driver_data = sc18is602 },
|
||||
{ .name = "sc18is602b", .driver_data = sc18is602b },
|
||||
{ .name = "sc18is603", .driver_data = sc18is603 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, sc18is602_id);
|
||||
|
|
|
|||
|
|
@ -224,15 +224,14 @@ static int hspi_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
ctlr = spi_alloc_host(&pdev->dev, sizeof(*hspi));
|
||||
ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*hspi));
|
||||
if (!ctlr)
|
||||
return -ENOMEM;
|
||||
|
||||
clk = clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(clk)) {
|
||||
dev_err(&pdev->dev, "couldn't get clock\n");
|
||||
ret = -EINVAL;
|
||||
goto error0;
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
|
||||
hspi = spi_controller_get_devdata(ctlr);
|
||||
|
|
@ -269,8 +268,6 @@ static int hspi_probe(struct platform_device *pdev)
|
|||
pm_runtime_disable(&pdev->dev);
|
||||
error1:
|
||||
clk_put(clk);
|
||||
error0:
|
||||
spi_controller_put(ctlr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -279,15 +276,11 @@ static void hspi_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct hspi_priv *hspi = platform_get_drvdata(pdev);
|
||||
|
||||
spi_controller_get(hspi->ctlr);
|
||||
|
||||
spi_unregister_controller(hspi->ctlr);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
clk_put(hspi->clk);
|
||||
|
||||
spi_controller_put(hspi->ctlr);
|
||||
}
|
||||
|
||||
static const struct of_device_id hspi_of_match[] = {
|
||||
|
|
|
|||
|
|
@ -1215,9 +1215,9 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
|
|||
info->dtdl = 200;
|
||||
|
||||
if (info->mode == MSIOF_SPI_TARGET)
|
||||
ctlr = spi_alloc_target(dev, sizeof(struct sh_msiof_spi_priv));
|
||||
ctlr = devm_spi_alloc_target(dev, sizeof(struct sh_msiof_spi_priv));
|
||||
else
|
||||
ctlr = spi_alloc_host(dev, sizeof(struct sh_msiof_spi_priv));
|
||||
ctlr = devm_spi_alloc_host(dev, sizeof(struct sh_msiof_spi_priv));
|
||||
if (ctlr == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -1234,26 +1234,21 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
|
|||
p->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(p->clk)) {
|
||||
dev_err(dev, "cannot get clock\n");
|
||||
ret = PTR_ERR(p->clk);
|
||||
goto err1;
|
||||
return PTR_ERR(p->clk);
|
||||
}
|
||||
|
||||
i = platform_get_irq(pdev, 0);
|
||||
if (i < 0) {
|
||||
ret = i;
|
||||
goto err1;
|
||||
}
|
||||
if (i < 0)
|
||||
return i;
|
||||
|
||||
p->mapbase = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(p->mapbase)) {
|
||||
ret = PTR_ERR(p->mapbase);
|
||||
goto err1;
|
||||
}
|
||||
if (IS_ERR(p->mapbase))
|
||||
return PTR_ERR(p->mapbase);
|
||||
|
||||
ret = devm_request_irq(dev, i, sh_msiof_spi_irq, 0, dev_name(dev), p);
|
||||
if (ret) {
|
||||
dev_err(dev, "unable to request irq\n");
|
||||
goto err1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
p->pdev = pdev;
|
||||
|
|
@ -1300,8 +1295,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
|
|||
err2:
|
||||
sh_msiof_release_dma(p);
|
||||
pm_runtime_disable(dev);
|
||||
err1:
|
||||
spi_controller_put(ctlr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1309,19 +1303,15 @@ static void sh_msiof_spi_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct sh_msiof_spi_priv *p = platform_get_drvdata(pdev);
|
||||
|
||||
spi_controller_get(p->ctlr);
|
||||
|
||||
spi_unregister_controller(p->ctlr);
|
||||
|
||||
sh_msiof_release_dma(p);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
spi_controller_put(p->ctlr);
|
||||
}
|
||||
|
||||
static const struct platform_device_id spi_driver_ids[] = {
|
||||
{ "spi_sh_msiof", (kernel_ulong_t)&sh_data },
|
||||
{},
|
||||
{ .name = "spi_sh_msiof", .driver_data = (kernel_ulong_t)&sh_data },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, spi_driver_ids);
|
||||
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ static int sifive_spi_probe(struct platform_device *pdev)
|
|||
u32 cs_bits, max_bits_per_word;
|
||||
struct spi_controller *host;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(struct sifive_spi));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(struct sifive_spi));
|
||||
if (!host) {
|
||||
dev_err(&pdev->dev, "out of memory\n");
|
||||
return -ENOMEM;
|
||||
|
|
@ -307,24 +307,19 @@ static int sifive_spi_probe(struct platform_device *pdev)
|
|||
platform_set_drvdata(pdev, host);
|
||||
|
||||
spi->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(spi->regs)) {
|
||||
ret = PTR_ERR(spi->regs);
|
||||
goto put_host;
|
||||
}
|
||||
if (IS_ERR(spi->regs))
|
||||
return PTR_ERR(spi->regs);
|
||||
|
||||
/* Spin up the bus clock before hitting registers */
|
||||
spi->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(spi->clk)) {
|
||||
dev_err(&pdev->dev, "Unable to find bus clock\n");
|
||||
ret = PTR_ERR(spi->clk);
|
||||
goto put_host;
|
||||
return PTR_ERR(spi->clk);
|
||||
}
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
ret = irq;
|
||||
goto put_host;
|
||||
}
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
/* Optional parameters */
|
||||
ret =
|
||||
|
|
@ -339,8 +334,7 @@ static int sifive_spi_probe(struct platform_device *pdev)
|
|||
|
||||
if (!ret && max_bits_per_word < 8) {
|
||||
dev_err(&pdev->dev, "Only 8bit SPI words supported by the driver\n");
|
||||
ret = -EINVAL;
|
||||
goto put_host;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* probe the number of CS lines */
|
||||
|
|
@ -350,15 +344,13 @@ static int sifive_spi_probe(struct platform_device *pdev)
|
|||
sifive_spi_write(spi, SIFIVE_SPI_REG_CSDEF, spi->cs_inactive);
|
||||
if (!cs_bits) {
|
||||
dev_err(&pdev->dev, "Could not auto probe CS lines\n");
|
||||
ret = -EINVAL;
|
||||
goto put_host;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
num_cs = ilog2(cs_bits) + 1;
|
||||
if (num_cs > SIFIVE_SPI_MAX_CS) {
|
||||
dev_err(&pdev->dev, "Invalid number of spi targets\n");
|
||||
ret = -EINVAL;
|
||||
goto put_host;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Define our host */
|
||||
|
|
@ -386,7 +378,7 @@ static int sifive_spi_probe(struct platform_device *pdev)
|
|||
dev_name(&pdev->dev), spi);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Unable to bind to interrupt\n");
|
||||
goto put_host;
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "mapped; irq=%d, cs=%d\n",
|
||||
|
|
@ -395,15 +387,10 @@ static int sifive_spi_probe(struct platform_device *pdev)
|
|||
ret = spi_register_controller(host);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "spi_register_host failed\n");
|
||||
goto put_host;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
put_host:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sifive_spi_remove(struct platform_device *pdev)
|
||||
|
|
@ -411,14 +398,10 @@ static void sifive_spi_remove(struct platform_device *pdev)
|
|||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct sifive_spi *spi = spi_controller_get_devdata(host);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
/* Disable all the interrupts just in case */
|
||||
sifive_spi_write(spi, SIFIVE_SPI_REG_IE, 0);
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
static int sifive_spi_suspend(struct device *dev)
|
||||
|
|
|
|||
|
|
@ -388,11 +388,9 @@ static int mtk_spi_slave_probe(struct platform_device *pdev)
|
|||
int irq, ret;
|
||||
const struct of_device_id *of_id;
|
||||
|
||||
ctlr = spi_alloc_target(&pdev->dev, sizeof(*mdata));
|
||||
if (!ctlr) {
|
||||
dev_err(&pdev->dev, "failed to alloc spi target\n");
|
||||
ctlr = devm_spi_alloc_target(&pdev->dev, sizeof(*mdata));
|
||||
if (!ctlr)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ctlr->auto_runtime_pm = true;
|
||||
ctlr->mode_bits = SPI_CPOL | SPI_CPHA;
|
||||
|
|
@ -406,8 +404,7 @@ static int mtk_spi_slave_probe(struct platform_device *pdev)
|
|||
of_id = of_match_node(mtk_spi_slave_of_match, pdev->dev.of_node);
|
||||
if (!of_id) {
|
||||
dev_err(&pdev->dev, "failed to probe of_node\n");
|
||||
ret = -EINVAL;
|
||||
goto err_put_ctlr;
|
||||
return -EINVAL;
|
||||
}
|
||||
mdata = spi_controller_get_devdata(ctlr);
|
||||
mdata->dev_comp = of_id->data;
|
||||
|
|
@ -420,35 +417,31 @@ static int mtk_spi_slave_probe(struct platform_device *pdev)
|
|||
init_completion(&mdata->xfer_done);
|
||||
mdata->dev = &pdev->dev;
|
||||
mdata->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(mdata->base)) {
|
||||
ret = PTR_ERR(mdata->base);
|
||||
goto err_put_ctlr;
|
||||
}
|
||||
if (IS_ERR(mdata->base))
|
||||
return PTR_ERR(mdata->base);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
ret = irq;
|
||||
goto err_put_ctlr;
|
||||
}
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, irq, mtk_spi_slave_interrupt,
|
||||
IRQF_TRIGGER_NONE, dev_name(&pdev->dev), ctlr);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register irq (%d)\n", ret);
|
||||
goto err_put_ctlr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
mdata->spi_clk = devm_clk_get(&pdev->dev, "spi");
|
||||
if (IS_ERR(mdata->spi_clk)) {
|
||||
ret = PTR_ERR(mdata->spi_clk);
|
||||
dev_err(&pdev->dev, "failed to get spi-clk: %d\n", ret);
|
||||
goto err_put_ctlr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(mdata->spi_clk);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to enable spi_clk (%d)\n", ret);
|
||||
goto err_put_ctlr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
|
@ -465,8 +458,6 @@ static int mtk_spi_slave_probe(struct platform_device *pdev)
|
|||
|
||||
err_disable_runtime_pm:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
err_put_ctlr:
|
||||
spi_controller_put(ctlr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -475,13 +466,9 @@ static void mtk_spi_slave_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct spi_controller *ctlr = platform_get_drvdata(pdev);
|
||||
|
||||
spi_controller_get(ctlr);
|
||||
|
||||
spi_unregister_controller(ctlr);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
spi_controller_put(ctlr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
|
|||
|
|
@ -222,9 +222,8 @@ static void f_ospi_config_clk(struct f_ospi *ospi, u32 device_hz)
|
|||
*/
|
||||
val = readl(ospi->base + OSPI_CLK_CTL);
|
||||
|
||||
val &= ~(OSPI_CLK_CTL_PHA | OSPI_CLK_CTL_DIV);
|
||||
val |= FIELD_PREP(OSPI_CLK_CTL_PHA, OSPI_CLK_CTL_PHA_180)
|
||||
| FIELD_PREP(OSPI_CLK_CTL_DIV, div_reg);
|
||||
FIELD_MODIFY(OSPI_CLK_CTL_PHA, &val, OSPI_CLK_CTL_PHA_180);
|
||||
FIELD_MODIFY(OSPI_CLK_CTL_DIV, &val, div_reg);
|
||||
|
||||
writel(val, ospi->base + OSPI_CLK_CTL);
|
||||
}
|
||||
|
|
|
|||
789
drivers/spi/spi-spacemit-k1.c
Normal file
789
drivers/spi/spi-spacemit-k1.c
Normal file
|
|
@ -0,0 +1,789 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// SpacemiT K1 SPI controller driver
|
||||
//
|
||||
// Copyright (C) 2026, RISCstar Solutions Corporation
|
||||
// Copyright (C) 2023, SpacemiT Corporation
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#include "internals.h"
|
||||
|
||||
/* This is the range of transfer rates supported by the K1 SoC */
|
||||
#define K1_SPI_MIN_SPEED_HZ 6250
|
||||
#define K1_SPI_MAX_SPEED_HZ 51200000
|
||||
|
||||
/* DMA constraints */
|
||||
#define K1_SPI_DMA_ALIGNMENT 64
|
||||
#define K1_SPI_MAX_DMA_LEN SZ_512K
|
||||
|
||||
/* SSP Top Control Register */
|
||||
#define SSP_TOP_CTRL 0x00
|
||||
#define TOP_SSE BIT(0) /* Enable port */
|
||||
#define TOP_FRF_MASK GENMASK(2, 1) /* Frame format */
|
||||
#define TOP_FRF_MOTOROLA 0 /* Motorola SPI */
|
||||
#define TOP_DSS_MASK GENMASK(9, 5) /* Data size (1-32) */
|
||||
#define TOP_SPO BIT(10) /* Polarity: 0=low */
|
||||
#define TOP_SPH BIT(11) /* Half-cycle phase */
|
||||
#define TOP_LBM BIT(12) /* Loopback mode */
|
||||
#define TOP_TRAIL BIT(13) /* Trailing bytes */
|
||||
#define TOP_HOLD_FRAME_LOW BIT(14) /* Chip select */
|
||||
|
||||
/* SSP FIFO Control Register */
|
||||
#define SSP_FIFO_CTRL 0x04
|
||||
#define FIFO_TFT_MASK GENMASK(4, 0) /* TX FIFO threshold */
|
||||
#define FIFO_RFT_MASK GENMASK(9, 5) /* RX FIFO threshold */
|
||||
#define FIFO_TSRE BIT(10) /* TX service request */
|
||||
#define FIFO_RSRE BIT(11) /* RX service request */
|
||||
|
||||
/* SSP Interrupt Enable Register */
|
||||
#define SSP_INT_EN 0x08
|
||||
#define SSP_INT_EN_TINTE BIT(1) /* RX timeout */
|
||||
#define SSP_INT_EN_RIE BIT(2) /* RX FIFO */
|
||||
#define SSP_INT_EN_TIE BIT(3) /* TX FIFO */
|
||||
#define SSP_INT_EN_RIM BIT(4) /* RX FIFO overrun */
|
||||
#define SSP_INT_EN_TIM BIT(5) /* TX FIFO underrun */
|
||||
#define SSP_INT_EN_EBCEI BIT(6) /* Bit count error */
|
||||
|
||||
/* TX interrupts, RX interrupts, and error interrupts */
|
||||
#define SSP_INT_EN_TX SSP_INT_EN_TIE
|
||||
#define SSP_INT_EN_RX \
|
||||
(SSP_INT_EN_TINTE | SSP_INT_EN_RIE)
|
||||
#define SSP_INT_EN_ERROR \
|
||||
(SSP_INT_EN_RIM | SSP_INT_EN_TIM | SSP_INT_EN_EBCEI)
|
||||
|
||||
/* SSP Time Out Register */
|
||||
#define SSP_TIMEOUT 0x0c
|
||||
#define SSP_TIMEOUT_MASK GENMASK(23, 0)
|
||||
|
||||
/* SSP Data Register */
|
||||
#define SSP_DATAR 0x10
|
||||
|
||||
/* SSP Status Register */
|
||||
#define SSP_STATUS 0x14
|
||||
#define SSP_STATUS_BSY BIT(0) /* SPI/I2S busy */
|
||||
#define SSP_STATUS_TNF BIT(6) /* TX FIFO not full */
|
||||
#define SSP_STATUS_TFL GENMASK(11, 7) /* TX FIFO level */
|
||||
#define SSP_STATUS_TUR BIT(12) /* TX FIFO underrun */
|
||||
#define SSP_STATUS_RNE BIT(14) /* RX FIFO not empty */
|
||||
#define SSP_STATUS_RFL GENMASK(19, 15) /* RX FIFO level */
|
||||
#define SSP_STATUS_ROR BIT(20) /* RX FIFO overrun */
|
||||
#define SSP_STATUS_BCE BIT(21) /* Bit count error */
|
||||
|
||||
/* Error status mask */
|
||||
#define SSP_STATUS_ERROR \
|
||||
(SSP_STATUS_TUR | SSP_STATUS_ROR | SSP_STATUS_BCE)
|
||||
|
||||
/* The FIFO sizes and thresholds are the same for RX and TX */
|
||||
#define K1_SPI_FIFO_SIZE 32
|
||||
#define K1_SPI_THRESH (K1_SPI_FIFO_SIZE / 2)
|
||||
|
||||
struct k1_spi_driver_data {
|
||||
struct spi_controller *host;
|
||||
void __iomem *base;
|
||||
phys_addr_t base_addr;
|
||||
unsigned long bus_rate;
|
||||
struct clk *clk;
|
||||
unsigned long rate;
|
||||
int irq;
|
||||
|
||||
/* Current transfer information; not valid if message is null */
|
||||
u32 bytes; /* Bytes used for bits_per_word */
|
||||
unsigned int rx_resid; /* RX bytes left in transfer */
|
||||
unsigned int tx_resid; /* TX bytes left in transfer */
|
||||
struct spi_transfer *transfer; /* Current transfer */
|
||||
|
||||
bool dma_enabled;
|
||||
};
|
||||
|
||||
/* Set our registers to a known initial state */
|
||||
static void
|
||||
k1_spi_register_reset(struct k1_spi_driver_data *drv_data, bool initial)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
writel(0, drv_data->base + SSP_TOP_CTRL);
|
||||
|
||||
if (initial) {
|
||||
/*
|
||||
* The TX and RX FIFO thresholds are the same no matter
|
||||
* what the speed or bits per word, so we can just set
|
||||
* them once. The thresholds are one more than the values
|
||||
* in the register.
|
||||
*/
|
||||
val = FIELD_PREP(FIFO_RFT_MASK, K1_SPI_THRESH - 1);
|
||||
val |= FIELD_PREP(FIFO_TFT_MASK, K1_SPI_THRESH - 1);
|
||||
}
|
||||
writel(val, drv_data->base + SSP_FIFO_CTRL);
|
||||
|
||||
writel(0, drv_data->base + SSP_INT_EN);
|
||||
writel(0, drv_data->base + SSP_TIMEOUT);
|
||||
|
||||
/* Clear any pending interrupt conditions */
|
||||
writel(~0, drv_data->base + SSP_STATUS);
|
||||
}
|
||||
|
||||
/*
|
||||
* The client can call the setup function multiple times, and each call
|
||||
* can specify a different SPI mode (and transfer speed). Each transfer
|
||||
* can specify its own speed though, and the core code ensures each
|
||||
* transfer's speed is set to something nonzero and supported by both
|
||||
* the controller and the device. We just set the speed for each transfer.
|
||||
*/
|
||||
static int k1_spi_setup(struct spi_device *spi)
|
||||
{
|
||||
struct k1_spi_driver_data *drv_data;
|
||||
u32 val;
|
||||
|
||||
drv_data = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
/*
|
||||
* Configure the message format for this device. We only
|
||||
* support Motorola SPI format in master mode.
|
||||
*/
|
||||
val = FIELD_PREP(TOP_FRF_MASK, TOP_FRF_MOTOROLA);
|
||||
|
||||
/* Translate the mode into the value used to program the hardware. */
|
||||
if (spi->mode & SPI_CPHA)
|
||||
val |= TOP_SPH; /* 1/2 cycle */
|
||||
if (spi->mode & SPI_CPOL)
|
||||
val |= TOP_SPO; /* active low */
|
||||
if (spi->mode & SPI_LOOP)
|
||||
val |= TOP_LBM; /* enable loopback */
|
||||
writel(val, drv_data->base + SSP_TOP_CTRL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void k1_spi_cleanup(struct spi_device *spi)
|
||||
{
|
||||
struct k1_spi_driver_data *drv_data;
|
||||
|
||||
drv_data = spi_controller_get_devdata(spi->controller);
|
||||
k1_spi_register_reset(drv_data, false);
|
||||
}
|
||||
|
||||
static bool k1_spi_can_dma(struct spi_controller *host, struct spi_device *spi,
|
||||
struct spi_transfer *transfer)
|
||||
{
|
||||
struct k1_spi_driver_data *drv_data = spi_controller_get_devdata(host);
|
||||
u32 burst_size;
|
||||
|
||||
if (!drv_data->dma_enabled)
|
||||
return false;
|
||||
|
||||
if (transfer->len > SZ_2K)
|
||||
return false;
|
||||
|
||||
/* Don't bother with DMA if we can't do even a single burst */
|
||||
burst_size = K1_SPI_THRESH * spi_bpw_to_bytes(transfer->bits_per_word);
|
||||
|
||||
return transfer->len >= burst_size;
|
||||
}
|
||||
|
||||
static void k1_spi_dma_callback(void *param)
|
||||
{
|
||||
struct k1_spi_driver_data *drv_data = param;
|
||||
u32 val;
|
||||
|
||||
val = readl(drv_data->base + SSP_FIFO_CTRL);
|
||||
val &= ~(FIFO_TSRE | FIFO_RSRE);
|
||||
writel(val, drv_data->base + SSP_FIFO_CTRL);
|
||||
|
||||
val = readl(drv_data->base + SSP_TOP_CTRL);
|
||||
val &= ~TOP_TRAIL;
|
||||
writel(val, drv_data->base + SSP_TOP_CTRL);
|
||||
|
||||
/* Check for any error conditions */
|
||||
val = readl(drv_data->base + SSP_STATUS);
|
||||
if (val & SSP_STATUS_ERROR)
|
||||
drv_data->transfer->error |= SPI_TRANS_FAIL_IO;
|
||||
|
||||
/* Disable the port */
|
||||
val = readl(drv_data->base + SSP_TOP_CTRL);
|
||||
val &= ~TOP_SSE;
|
||||
writel(val, drv_data->base + SSP_TOP_CTRL);
|
||||
|
||||
drv_data->transfer = NULL;
|
||||
|
||||
spi_finalize_current_transfer(drv_data->host);
|
||||
}
|
||||
|
||||
/* Prepare a descriptor for TX or RX DMA */
|
||||
static struct dma_async_tx_descriptor *
|
||||
k1_spi_dma_prep(struct k1_spi_driver_data *drv_data,
|
||||
struct spi_transfer *transfer, bool tx)
|
||||
{
|
||||
phys_addr_t addr = drv_data->base_addr + SSP_DATAR;
|
||||
u32 burst_size = K1_SPI_THRESH * drv_data->bytes;
|
||||
struct dma_slave_config cfg = { };
|
||||
enum dma_transfer_direction dir;
|
||||
enum dma_slave_buswidth width;
|
||||
struct dma_chan *chan;
|
||||
struct sg_table *sgt;
|
||||
|
||||
switch (drv_data->bytes) {
|
||||
case 1:
|
||||
width = DMA_SLAVE_BUSWIDTH_1_BYTE;
|
||||
break;
|
||||
case 2:
|
||||
width = DMA_SLAVE_BUSWIDTH_2_BYTES;
|
||||
break;
|
||||
default: /* bytes == 4 */
|
||||
width = DMA_SLAVE_BUSWIDTH_4_BYTES;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tx) {
|
||||
chan = drv_data->host->dma_tx;
|
||||
sgt = &transfer->tx_sg;
|
||||
dir = DMA_MEM_TO_DEV;
|
||||
|
||||
cfg.dst_addr = addr;
|
||||
cfg.dst_addr_width = width;
|
||||
cfg.dst_maxburst = burst_size;
|
||||
} else {
|
||||
chan = drv_data->host->dma_rx;
|
||||
sgt = &transfer->rx_sg;
|
||||
dir = DMA_DEV_TO_MEM;
|
||||
|
||||
cfg.src_addr = addr;
|
||||
cfg.src_addr_width = width;
|
||||
cfg.src_maxburst = burst_size;
|
||||
}
|
||||
cfg.direction = dir;
|
||||
|
||||
if (dmaengine_slave_config(chan, &cfg))
|
||||
return NULL;
|
||||
|
||||
return dmaengine_prep_slave_sg(chan, sgt->sgl, sgt->nents, dir,
|
||||
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||
|
||||
}
|
||||
|
||||
static int k1_spi_dma_one(struct spi_controller *host, struct spi_device *spi,
|
||||
struct spi_transfer *transfer)
|
||||
{
|
||||
struct k1_spi_driver_data *drv_data = spi_controller_get_devdata(host);
|
||||
struct dma_async_tx_descriptor *desc;
|
||||
u32 val;
|
||||
|
||||
/* Prepare the TX descriptor and submit it */
|
||||
desc = k1_spi_dma_prep(drv_data, transfer, true);
|
||||
if (!desc)
|
||||
goto fallback;
|
||||
dmaengine_submit(desc);
|
||||
|
||||
/* Prepare the RX descriptor and submit it */
|
||||
desc = k1_spi_dma_prep(drv_data, transfer, false);
|
||||
if (!desc)
|
||||
goto fallback;
|
||||
|
||||
/* When RX is complete we also know TX has completed */
|
||||
desc->callback = k1_spi_dma_callback;
|
||||
desc->callback_param = drv_data;
|
||||
|
||||
dmaengine_submit(desc);
|
||||
|
||||
val = readl(drv_data->base + SSP_TOP_CTRL);
|
||||
val |= TOP_TRAIL; /* Trailing bytes handled by DMA */
|
||||
writel(val, drv_data->base + SSP_TOP_CTRL);
|
||||
|
||||
val = readl(drv_data->base + SSP_FIFO_CTRL);
|
||||
val |= FIFO_TSRE | FIFO_RSRE;
|
||||
writel(val, drv_data->base + SSP_FIFO_CTRL);
|
||||
|
||||
/* Start RX first so we're ready the instant we start transmitting */
|
||||
dma_async_issue_pending(host->dma_rx);
|
||||
dma_async_issue_pending(host->dma_tx);
|
||||
|
||||
return 1;
|
||||
fallback:
|
||||
transfer->error |= SPI_TRANS_FAIL_NO_START;
|
||||
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
/* Flush the RX FIFO of any leftover data before processing a message */
|
||||
static int k1_spi_prepare_message(struct spi_controller *host,
|
||||
struct spi_message *message)
|
||||
{
|
||||
struct k1_spi_driver_data *drv_data = spi_controller_get_devdata(host);
|
||||
u32 val = readl(drv_data->base + SSP_STATUS);
|
||||
u32 count;
|
||||
|
||||
/* If there's nothing in the FIFO, we're done */
|
||||
if (!(val & SSP_STATUS_RNE))
|
||||
return 0;
|
||||
|
||||
/* Read and discard what's there (one more than what the field says) */
|
||||
count = FIELD_GET(SSP_STATUS_RFL, val) + 1;
|
||||
do
|
||||
(void)readl(drv_data->base + SSP_DATAR);
|
||||
while (--count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set logic level of chip select line (high=true means CS deasserted) */
|
||||
static void k1_spi_set_cs(struct spi_device *spi, bool high)
|
||||
{
|
||||
struct k1_spi_driver_data *drv_data;
|
||||
u32 val;
|
||||
|
||||
drv_data = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
val = readl(drv_data->base + SSP_TOP_CTRL);
|
||||
if (high)
|
||||
val &= ~TOP_HOLD_FRAME_LOW;
|
||||
else
|
||||
val |= TOP_HOLD_FRAME_LOW;
|
||||
writel(val, drv_data->base + SSP_TOP_CTRL);
|
||||
}
|
||||
|
||||
/* Set the transfer speed; the SPI core code ensures it is supported */
|
||||
static int k1_spi_set_speed(struct k1_spi_driver_data *drv_data,
|
||||
struct spi_transfer *transfer)
|
||||
{
|
||||
struct clk *clk = drv_data->clk;
|
||||
u64 nsec_per_word;
|
||||
u64 bus_ticks;
|
||||
u32 timeout;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
ret = clk_set_rate(clk, transfer->speed_hz);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drv_data->rate = clk_get_rate(clk);
|
||||
|
||||
/* No need for RX FIFO timeout if we're not receiving anything */
|
||||
if (!transfer->rx_buf)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Compute the RX FIFO inactivity timeout value that should be used.
|
||||
* The inactivity timer restarts with each word that lands in the
|
||||
* FIFO. If several "word transfer times" pass without any new data
|
||||
* in the RX FIFO, we might as well read what's there.
|
||||
*
|
||||
* The rate at which words land in the FIFO is determined by the
|
||||
* word size and the transfer rate. One bit is transferred per
|
||||
* clock tick, and 8 (or 16 or 32) bits are transferred per word.
|
||||
*
|
||||
* So we can get word transfer time (in nanoseconds) from:
|
||||
* nsec_per_tick = NSEC_PER_SEC / drv_data->rate;
|
||||
* ticks_per_word = BITS_PER_BYTE * drv_data->bytes;
|
||||
* We do the divide last for better accuracy.
|
||||
*/
|
||||
nsec_per_word = (u64)NSEC_PER_SEC * BITS_PER_BYTE * drv_data->bytes;
|
||||
nsec_per_word = DIV_ROUND_UP_ULL(nsec_per_word, drv_data->rate);
|
||||
|
||||
/*
|
||||
* The timeout (which we'll set to three word transfer times) is
|
||||
* expressed as a number of APB clock ticks.
|
||||
* bus_ticks = 3 * nsec * (drv_data->bus_rate / NSEC_PER_SEC)
|
||||
*/
|
||||
bus_ticks = 3 * nsec_per_word * drv_data->bus_rate;
|
||||
timeout = DIV_ROUND_UP_ULL(bus_ticks, NSEC_PER_SEC);
|
||||
|
||||
/* Set the RX timeout period (required for both DMA and PIO) */
|
||||
val = FIELD_PREP(SSP_TIMEOUT_MASK, timeout);
|
||||
writel(val, drv_data->base + SSP_TIMEOUT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int k1_spi_transfer_one(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *transfer)
|
||||
{
|
||||
struct k1_spi_driver_data *drv_data = spi_controller_get_devdata(host);
|
||||
u32 ctrl;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
/* Bits per word can change on a per-transfer basis */
|
||||
drv_data->bytes = spi_bpw_to_bytes(transfer->bits_per_word);
|
||||
|
||||
/* Each transfer can also specify a different rate */
|
||||
ret = k1_spi_set_speed(drv_data, transfer);
|
||||
if (ret) {
|
||||
dev_err(&host->dev,
|
||||
"failed to set transfer speed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
drv_data->rx_resid = transfer->len;
|
||||
drv_data->tx_resid = transfer->len;
|
||||
|
||||
drv_data->transfer = transfer;
|
||||
|
||||
/* Clear any existing interrupt conditions */
|
||||
writel(~0, drv_data->base + SSP_STATUS);
|
||||
|
||||
/* Set the data (word) size, and enable the port */
|
||||
ctrl = readl(drv_data->base + SSP_TOP_CTRL);
|
||||
ctrl &= ~TOP_DSS_MASK;
|
||||
ctrl |= FIELD_PREP(TOP_DSS_MASK, transfer->bits_per_word - 1);
|
||||
ctrl |= TOP_SSE;
|
||||
writel(ctrl, drv_data->base + SSP_TOP_CTRL);
|
||||
|
||||
if (spi_xfer_is_dma_mapped(host, spi, transfer))
|
||||
return k1_spi_dma_one(host, spi, transfer);
|
||||
|
||||
/* An interrupt will initiate the transfer */
|
||||
val = SSP_INT_EN_TX | SSP_INT_EN_RX | SSP_INT_EN_ERROR;
|
||||
writel(val, drv_data->base + SSP_INT_EN);
|
||||
|
||||
return 1; /* We will call spi_finalize_current_transfer() */
|
||||
}
|
||||
|
||||
static void
|
||||
k1_spi_handle_err(struct spi_controller *host, struct spi_message *message)
|
||||
{
|
||||
struct k1_spi_driver_data *drv_data = spi_controller_get_devdata(host);
|
||||
|
||||
if (drv_data->dma_enabled) {
|
||||
dmaengine_terminate_sync(host->dma_rx);
|
||||
dmaengine_terminate_sync(host->dma_tx);
|
||||
}
|
||||
}
|
||||
|
||||
static void k1_spi_write_word(struct k1_spi_driver_data *drv_data)
|
||||
{
|
||||
struct spi_transfer *transfer = drv_data->transfer;
|
||||
u32 bytes = drv_data->bytes;
|
||||
u32 val;
|
||||
|
||||
if (transfer->tx_buf) {
|
||||
const void *buf;
|
||||
|
||||
buf = transfer->tx_buf + (transfer->len - drv_data->tx_resid);
|
||||
if (bytes == 1)
|
||||
val = *(u8 *)buf;
|
||||
else if (bytes == 2)
|
||||
val = *(u16 *)buf;
|
||||
else /* bytes == 4 */
|
||||
val = *(u32 *)buf;
|
||||
} else {
|
||||
val = 0; /* Null writer; write 1, 2, or 4 zero bytes */
|
||||
}
|
||||
/* Fill the next TX FIFO entry */
|
||||
writel(val, drv_data->base + SSP_DATAR);
|
||||
|
||||
drv_data->tx_resid -= bytes;
|
||||
}
|
||||
|
||||
/* The last-read status value is provided; we know SSP_STATUS_TNF is set */
|
||||
static bool k1_spi_write(struct k1_spi_driver_data *drv_data, u32 val)
|
||||
{
|
||||
unsigned int count;
|
||||
|
||||
/* Get the number of open slots in the FIFO; zero means all */
|
||||
count = FIELD_GET(SSP_STATUS_TFL, val) ? : K1_SPI_FIFO_SIZE;
|
||||
|
||||
/*
|
||||
* Limit how much we try to send at a time, to reduce the
|
||||
* chance the other side can overrun our RX FIFO.
|
||||
*/
|
||||
count = min3(count, K1_SPI_THRESH, drv_data->tx_resid / drv_data->bytes);
|
||||
do
|
||||
k1_spi_write_word(drv_data);
|
||||
while (--count);
|
||||
|
||||
return !drv_data->tx_resid;
|
||||
}
|
||||
|
||||
static void k1_spi_read_word(struct k1_spi_driver_data *drv_data)
|
||||
{
|
||||
struct spi_transfer *transfer = drv_data->transfer;
|
||||
u32 bytes = drv_data->bytes;
|
||||
u32 val;
|
||||
|
||||
/* Consume the next RX FIFO entry */
|
||||
val = readl(drv_data->base + SSP_DATAR);
|
||||
if (transfer->rx_buf) {
|
||||
void *buf;
|
||||
|
||||
buf = transfer->rx_buf + (transfer->len - drv_data->rx_resid);
|
||||
|
||||
if (bytes == 1)
|
||||
*(u8 *)buf = val;
|
||||
else if (bytes == 2)
|
||||
*(u16 *)buf = val;
|
||||
else /* bytes == 4 */
|
||||
*(u32 *)buf = val;
|
||||
} /* Otherwise null reader: discard the data */
|
||||
|
||||
drv_data->rx_resid -= bytes;
|
||||
}
|
||||
|
||||
/* The last-read status value is provided; we know SSP_STATUS_RNE is set */
|
||||
static bool k1_spi_read(struct k1_spi_driver_data *drv_data, u32 val)
|
||||
{
|
||||
do {
|
||||
unsigned int count = FIELD_GET(SSP_STATUS_RFL, val) + 1;
|
||||
|
||||
/* Only read what we need */
|
||||
count = min(count, drv_data->rx_resid / drv_data->bytes);
|
||||
do
|
||||
k1_spi_read_word(drv_data);
|
||||
while (--count);
|
||||
|
||||
/* If there's no more to read, we're done */
|
||||
if (!drv_data->rx_resid)
|
||||
return true;
|
||||
|
||||
/* Check again in case more became available to read */
|
||||
val = readl(drv_data->base + SSP_STATUS);
|
||||
if (val & SSP_STATUS_RNE)
|
||||
writel(SSP_STATUS_RNE, drv_data->base + SSP_STATUS);
|
||||
else
|
||||
return false;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
static irqreturn_t k1_spi_ssp_isr(int irq, void *dev_id)
|
||||
{
|
||||
struct k1_spi_driver_data *drv_data = dev_id;
|
||||
u32 status;
|
||||
u32 top_ctrl;
|
||||
|
||||
/* Get status and clear pending interrupts */
|
||||
status = readl(drv_data->base + SSP_STATUS);
|
||||
writel(status, drv_data->base + SSP_STATUS);
|
||||
|
||||
/* If no actionable status bits are set, this is not our interrupt */
|
||||
if (!(status & (SSP_STATUS_ERROR | SSP_STATUS_TNF | SSP_STATUS_RNE)))
|
||||
return IRQ_NONE;
|
||||
|
||||
/* Check for any error conditions first */
|
||||
if (status & SSP_STATUS_ERROR) {
|
||||
if (drv_data->transfer)
|
||||
drv_data->transfer->error |= SPI_TRANS_FAIL_IO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* For SPI, bytes are transferred in both directions equally, and
|
||||
* RX always follows TX. Start by writing if there is anything to
|
||||
* write, then read. Once there's no more to read, we're done.
|
||||
*/
|
||||
if (drv_data->tx_resid && (status & SSP_STATUS_TNF)) {
|
||||
/* If we finish writing, disable TX interrupts */
|
||||
if (k1_spi_write(drv_data, status))
|
||||
writel(SSP_INT_EN_RX | SSP_INT_EN_ERROR,
|
||||
drv_data->base + SSP_INT_EN);
|
||||
}
|
||||
|
||||
/* We're not done unless we've read all that was requested */
|
||||
if (drv_data->rx_resid) {
|
||||
/* Read more if the FIFO is not empty */
|
||||
if (status & SSP_STATUS_RNE)
|
||||
if (k1_spi_read(drv_data, status))
|
||||
goto done;
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
done:
|
||||
/* Disable the port */
|
||||
top_ctrl = readl(drv_data->base + SSP_TOP_CTRL);
|
||||
top_ctrl &= ~TOP_SSE;
|
||||
writel(top_ctrl, drv_data->base + SSP_TOP_CTRL);
|
||||
|
||||
/* Disable all interrupts */
|
||||
writel(0, drv_data->base + SSP_INT_EN);
|
||||
|
||||
if (drv_data->transfer) {
|
||||
drv_data->transfer = NULL;
|
||||
spi_finalize_current_transfer(drv_data->host);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int
|
||||
k1_spi_dma_setup(struct k1_spi_driver_data *drv_data, struct device *dev)
|
||||
{
|
||||
struct spi_controller *host = drv_data->host;
|
||||
struct dma_chan *chan;
|
||||
|
||||
chan = dma_request_chan(dev, "tx");
|
||||
if (IS_ERR(chan))
|
||||
return PTR_ERR(chan);
|
||||
host->dma_tx = chan;
|
||||
|
||||
chan = dma_request_chan(dev, "rx");
|
||||
if (IS_ERR(chan)) {
|
||||
dma_release_channel(host->dma_tx);
|
||||
host->dma_tx = NULL;
|
||||
return PTR_ERR(chan);
|
||||
}
|
||||
host->dma_rx = chan;
|
||||
|
||||
drv_data->dma_enabled = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void k1_spi_dma_cleanup(struct device *dev, void *res)
|
||||
{
|
||||
struct k1_spi_driver_data **ptr = res;
|
||||
struct k1_spi_driver_data *drv_data = *ptr;
|
||||
struct spi_controller *host = drv_data->host;
|
||||
|
||||
if (!drv_data->dma_enabled)
|
||||
return;
|
||||
|
||||
drv_data->dma_enabled = false;
|
||||
|
||||
dma_release_channel(host->dma_rx);
|
||||
host->dma_rx = NULL;
|
||||
dma_release_channel(host->dma_tx);
|
||||
host->dma_tx = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
devm_k1_spi_dma_setup(struct k1_spi_driver_data *drv_data, struct device *dev)
|
||||
{
|
||||
struct k1_spi_driver_data **ptr;
|
||||
int ret;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_MMP_PDMA)) {
|
||||
dev_info(dev, "DMA not available; using PIO\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ptr = devres_alloc(k1_spi_dma_cleanup, sizeof(*ptr), GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = k1_spi_dma_setup(drv_data, dev);
|
||||
if (ret) {
|
||||
devres_free(ptr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*ptr = drv_data;
|
||||
devres_add(dev, ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int k1_spi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct k1_spi_driver_data *drv_data;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct reset_control *reset;
|
||||
struct spi_controller *host;
|
||||
struct resource *iores;
|
||||
struct clk *clk_bus;
|
||||
int ret;
|
||||
|
||||
host = devm_spi_alloc_host(dev, sizeof(*drv_data));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
drv_data = spi_controller_get_devdata(host);
|
||||
drv_data->host = host;
|
||||
platform_set_drvdata(pdev, drv_data);
|
||||
|
||||
ret = devm_k1_spi_dma_setup(drv_data, dev);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return ret;
|
||||
if (ret)
|
||||
dev_warn(dev, "DMA setup failed (%d), falling back to PIO\n", ret);
|
||||
|
||||
drv_data->base = devm_platform_get_and_ioremap_resource(pdev, 0,
|
||||
&iores);
|
||||
if (IS_ERR(drv_data->base))
|
||||
return dev_err_probe(dev, PTR_ERR(drv_data->base),
|
||||
"error mapping memory\n");
|
||||
drv_data->base_addr = iores->start;
|
||||
|
||||
clk_bus = devm_clk_get_enabled(dev, "bus");
|
||||
if (IS_ERR(clk_bus))
|
||||
return dev_err_probe(dev, PTR_ERR(clk_bus),
|
||||
"error getting/enabling bus clock\n");
|
||||
drv_data->bus_rate = clk_get_rate(clk_bus);
|
||||
|
||||
drv_data->clk = devm_clk_get_enabled(dev, "core");
|
||||
if (IS_ERR(drv_data->clk))
|
||||
return dev_err_probe(dev, PTR_ERR(drv_data->clk),
|
||||
"error getting/enabling core clock\n");
|
||||
|
||||
reset = devm_reset_control_get_exclusive_deasserted(dev, NULL);
|
||||
if (IS_ERR(reset))
|
||||
return dev_err_probe(dev, PTR_ERR(reset),
|
||||
"error getting/deasserting reset\n");
|
||||
|
||||
k1_spi_register_reset(drv_data, true);
|
||||
|
||||
drv_data->irq = platform_get_irq(pdev, 0);
|
||||
if (drv_data->irq < 0)
|
||||
return dev_err_probe(dev, drv_data->irq, "error getting IRQ\n");
|
||||
|
||||
ret = devm_request_irq(dev, drv_data->irq, k1_spi_ssp_isr,
|
||||
IRQF_SHARED, dev_name(dev), drv_data);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "error requesting IRQ\n");
|
||||
|
||||
/* Initialize the host structure, then register it */
|
||||
host->dev.of_node = dev_of_node(dev);
|
||||
host->dev.parent = dev;
|
||||
host->num_chipselect = 1;
|
||||
if (drv_data->dma_enabled)
|
||||
host->dma_alignment = K1_SPI_DMA_ALIGNMENT;
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP;
|
||||
host->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
|
||||
host->min_speed_hz = K1_SPI_MIN_SPEED_HZ;
|
||||
host->max_speed_hz = K1_SPI_MAX_SPEED_HZ;
|
||||
host->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX;
|
||||
host->max_dma_len = K1_SPI_MAX_DMA_LEN;
|
||||
|
||||
host->setup = k1_spi_setup;
|
||||
host->cleanup = k1_spi_cleanup;
|
||||
host->can_dma = k1_spi_can_dma;
|
||||
host->prepare_message = k1_spi_prepare_message;
|
||||
host->set_cs = k1_spi_set_cs;
|
||||
host->transfer_one = k1_spi_transfer_one;
|
||||
host->handle_err = k1_spi_handle_err;
|
||||
|
||||
ret = devm_spi_register_controller(dev, host);
|
||||
if (ret)
|
||||
dev_err(dev, "error registering controller\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id k1_spi_dt_ids[] = {
|
||||
{ .compatible = "spacemit,k1-spi", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, k1_spi_dt_ids);
|
||||
|
||||
static struct platform_driver k1_spi_driver = {
|
||||
.probe = k1_spi_probe,
|
||||
.driver = {
|
||||
.name = "k1-spi",
|
||||
.of_match_table = k1_spi_dt_ids,
|
||||
},
|
||||
};
|
||||
module_platform_driver(k1_spi_driver);
|
||||
|
||||
MODULE_DESCRIPTION("SpacemiT K1 SPI controller driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -923,16 +923,14 @@ static int sprd_spi_probe(struct platform_device *pdev)
|
|||
int ret;
|
||||
|
||||
pdev->id = of_alias_get_id(pdev->dev.of_node, "spi");
|
||||
sctlr = spi_alloc_host(&pdev->dev, sizeof(*ss));
|
||||
sctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*ss));
|
||||
if (!sctlr)
|
||||
return -ENOMEM;
|
||||
|
||||
ss = spi_controller_get_devdata(sctlr);
|
||||
ss->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
if (IS_ERR(ss->base)) {
|
||||
ret = PTR_ERR(ss->base);
|
||||
goto free_controller;
|
||||
}
|
||||
if (IS_ERR(ss->base))
|
||||
return PTR_ERR(ss->base);
|
||||
|
||||
ss->phy_base = res->start;
|
||||
ss->dev = &pdev->dev;
|
||||
|
|
@ -949,15 +947,15 @@ static int sprd_spi_probe(struct platform_device *pdev)
|
|||
platform_set_drvdata(pdev, sctlr);
|
||||
ret = sprd_spi_clk_init(pdev, ss);
|
||||
if (ret)
|
||||
goto free_controller;
|
||||
return ret;
|
||||
|
||||
ret = sprd_spi_irq_init(pdev, ss);
|
||||
if (ret)
|
||||
goto free_controller;
|
||||
return ret;
|
||||
|
||||
ret = sprd_spi_dma_init(pdev, ss);
|
||||
if (ret)
|
||||
goto free_controller;
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(ss->clk);
|
||||
if (ret)
|
||||
|
|
@ -993,8 +991,6 @@ static int sprd_spi_probe(struct platform_device *pdev)
|
|||
release_dma:
|
||||
if (ss->dma.enable)
|
||||
sprd_spi_dma_release(ss);
|
||||
free_controller:
|
||||
spi_controller_put(sctlr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1009,8 +1005,6 @@ static void sprd_spi_remove(struct platform_device *pdev)
|
|||
if (ret < 0)
|
||||
dev_err(ss->dev, "failed to resume SPI controller\n");
|
||||
|
||||
spi_controller_get(sctlr);
|
||||
|
||||
spi_unregister_controller(sctlr);
|
||||
|
||||
if (ret >= 0) {
|
||||
|
|
@ -1020,8 +1014,6 @@ static void sprd_spi_remove(struct platform_device *pdev)
|
|||
}
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
spi_controller_put(sctlr);
|
||||
}
|
||||
|
||||
static int __maybe_unused sprd_spi_runtime_suspend(struct device *dev)
|
||||
|
|
|
|||
|
|
@ -279,7 +279,7 @@ static int spi_st_probe(struct platform_device *pdev)
|
|||
int irq, ret = 0;
|
||||
u32 var;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*spi_st));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*spi_st));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -296,13 +296,12 @@ static int spi_st_probe(struct platform_device *pdev)
|
|||
spi_st->clk = devm_clk_get(&pdev->dev, "ssc");
|
||||
if (IS_ERR(spi_st->clk)) {
|
||||
dev_err(&pdev->dev, "Unable to request clock\n");
|
||||
ret = PTR_ERR(spi_st->clk);
|
||||
goto put_host;
|
||||
return PTR_ERR(spi_st->clk);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(spi_st->clk);
|
||||
if (ret)
|
||||
goto put_host;
|
||||
return ret;
|
||||
|
||||
init_completion(&spi_st->done);
|
||||
|
||||
|
|
@ -361,8 +360,7 @@ static int spi_st_probe(struct platform_device *pdev)
|
|||
pm_runtime_disable(&pdev->dev);
|
||||
clk_disable:
|
||||
clk_disable_unprepare(spi_st->clk);
|
||||
put_host:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -371,16 +369,12 @@ static void spi_st_remove(struct platform_device *pdev)
|
|||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct spi_st *spi_st = spi_controller_get_devdata(host);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
clk_disable_unprepare(spi_st->clk);
|
||||
|
||||
spi_controller_put(host);
|
||||
|
||||
pinctrl_pm_select_sleep_state(&pdev->dev);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -470,10 +470,9 @@ static int stm32_ospi_send(struct spi_device *spi, const struct spi_mem_op *op)
|
|||
u8 cs = spi->chip_select[ffs(spi->cs_index_mask) - 1];
|
||||
|
||||
cr = readl_relaxed(ospi->regs_base + OSPI_CR);
|
||||
cr &= ~CR_CSSEL;
|
||||
cr |= FIELD_PREP(CR_CSSEL, cs);
|
||||
cr &= ~CR_FMODE_MASK;
|
||||
cr |= FIELD_PREP(CR_FMODE_MASK, ospi->fmode);
|
||||
FIELD_MODIFY(CR_CSSEL, &cr, cs);
|
||||
|
||||
FIELD_MODIFY(CR_FMODE_MASK, &cr, ospi->fmode);
|
||||
writel_relaxed(cr, regs_base + OSPI_CR);
|
||||
|
||||
if (op->data.nbytes)
|
||||
|
|
@ -602,11 +601,11 @@ static int stm32_ospi_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
|||
{
|
||||
struct stm32_ospi *ospi = spi_controller_get_devdata(desc->mem->spi->controller);
|
||||
|
||||
if (desc->info.op_tmpl.data.dir == SPI_MEM_DATA_OUT)
|
||||
if (desc->info.op_tmpl->data.dir == SPI_MEM_DATA_OUT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Should never happen, as mm_base == null is an error probe exit condition */
|
||||
if (!ospi->mm_base && desc->info.op_tmpl.data.dir == SPI_MEM_DATA_IN)
|
||||
if (!ospi->mm_base && desc->info.op_tmpl->data.dir == SPI_MEM_DATA_IN)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!ospi->mm_size)
|
||||
|
|
@ -633,7 +632,7 @@ static ssize_t stm32_ospi_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
|||
* spi_mem_op template with offs, len and *buf in order to get
|
||||
* all needed transfer information into struct spi_mem_op
|
||||
*/
|
||||
memcpy(&op, &desc->info.op_tmpl, sizeof(struct spi_mem_op));
|
||||
memcpy(&op, desc->info.op_tmpl, sizeof(struct spi_mem_op));
|
||||
dev_dbg(ospi->dev, "%s len = 0x%zx offs = 0x%llx buf = 0x%p\n", __func__, len, offs, buf);
|
||||
|
||||
op.data.nbytes = len;
|
||||
|
|
|
|||
|
|
@ -374,9 +374,8 @@ static int stm32_qspi_send(struct spi_device *spi, const struct spi_mem_op *op)
|
|||
int timeout, err = 0, err_poll_status = 0;
|
||||
|
||||
cr = readl_relaxed(qspi->io_base + QSPI_CR);
|
||||
cr &= ~CR_PRESC_MASK & ~CR_FSEL;
|
||||
cr |= FIELD_PREP(CR_PRESC_MASK, flash->presc);
|
||||
cr |= FIELD_PREP(CR_FSEL, flash->cs);
|
||||
FIELD_MODIFY(CR_PRESC_MASK, &cr, flash->presc);
|
||||
FIELD_MODIFY(CR_FSEL, &cr, flash->cs);
|
||||
writel_relaxed(cr, qspi->io_base + QSPI_CR);
|
||||
|
||||
if (op->data.nbytes)
|
||||
|
|
@ -506,11 +505,11 @@ static int stm32_qspi_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
|||
{
|
||||
struct stm32_qspi *qspi = spi_controller_get_devdata(desc->mem->spi->controller);
|
||||
|
||||
if (desc->info.op_tmpl.data.dir == SPI_MEM_DATA_OUT)
|
||||
if (desc->info.op_tmpl->data.dir == SPI_MEM_DATA_OUT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* should never happen, as mm_base == null is an error probe exit condition */
|
||||
if (!qspi->mm_base && desc->info.op_tmpl.data.dir == SPI_MEM_DATA_IN)
|
||||
if (!qspi->mm_base && desc->info.op_tmpl->data.dir == SPI_MEM_DATA_IN)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!qspi->mm_size)
|
||||
|
|
@ -536,7 +535,7 @@ static ssize_t stm32_qspi_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
|||
* spi_mem_op template with offs, len and *buf in order to get
|
||||
* all needed transfer information into struct spi_mem_op
|
||||
*/
|
||||
memcpy(&op, &desc->info.op_tmpl, sizeof(struct spi_mem_op));
|
||||
memcpy(&op, desc->info.op_tmpl, sizeof(struct spi_mem_op));
|
||||
dev_dbg(qspi->dev, "%s len = 0x%zx offs = 0x%llx buf = 0x%p\n", __func__, len, offs, buf);
|
||||
|
||||
op.data.nbytes = len;
|
||||
|
|
|
|||
|
|
@ -434,32 +434,26 @@ static int sun4i_spi_probe(struct platform_device *pdev)
|
|||
struct sun4i_spi *sspi;
|
||||
int ret = 0, irq;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(struct sun4i_spi));
|
||||
if (!host) {
|
||||
dev_err(&pdev->dev, "Unable to allocate SPI Host\n");
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(struct sun4i_spi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, host);
|
||||
sspi = spi_controller_get_devdata(host);
|
||||
|
||||
sspi->base_addr = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(sspi->base_addr)) {
|
||||
ret = PTR_ERR(sspi->base_addr);
|
||||
goto err_free_host;
|
||||
}
|
||||
if (IS_ERR(sspi->base_addr))
|
||||
return PTR_ERR(sspi->base_addr);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
ret = -ENXIO;
|
||||
goto err_free_host;
|
||||
}
|
||||
if (irq < 0)
|
||||
return -ENXIO;
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, irq, sun4i_spi_handler,
|
||||
0, "sun4i-spi", sspi);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Cannot request IRQ\n");
|
||||
goto err_free_host;
|
||||
return ret;
|
||||
}
|
||||
|
||||
sspi->host = host;
|
||||
|
|
@ -477,15 +471,13 @@ static int sun4i_spi_probe(struct platform_device *pdev)
|
|||
sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
|
||||
if (IS_ERR(sspi->hclk)) {
|
||||
dev_err(&pdev->dev, "Unable to acquire AHB clock\n");
|
||||
ret = PTR_ERR(sspi->hclk);
|
||||
goto err_free_host;
|
||||
return PTR_ERR(sspi->hclk);
|
||||
}
|
||||
|
||||
sspi->mclk = devm_clk_get(&pdev->dev, "mod");
|
||||
if (IS_ERR(sspi->mclk)) {
|
||||
dev_err(&pdev->dev, "Unable to acquire module clock\n");
|
||||
ret = PTR_ERR(sspi->mclk);
|
||||
goto err_free_host;
|
||||
return PTR_ERR(sspi->mclk);
|
||||
}
|
||||
|
||||
init_completion(&sspi->done);
|
||||
|
|
@ -497,7 +489,7 @@ static int sun4i_spi_probe(struct platform_device *pdev)
|
|||
ret = sun4i_spi_runtime_resume(&pdev->dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Couldn't resume the device\n");
|
||||
goto err_free_host;
|
||||
return ret;
|
||||
}
|
||||
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
|
|
@ -515,8 +507,7 @@ static int sun4i_spi_probe(struct platform_device *pdev)
|
|||
err_pm_disable:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
sun4i_spi_runtime_suspend(&pdev->dev);
|
||||
err_free_host:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -524,13 +515,9 @@ static void sun4i_spi_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
pm_runtime_force_suspend(&pdev->dev);
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
static const struct of_device_id sun4i_spi_match[] = {
|
||||
|
|
|
|||
|
|
@ -633,7 +633,7 @@ static int sun6i_spi_probe(struct platform_device *pdev)
|
|||
struct resource *mem;
|
||||
int ret = 0, irq;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(struct sun6i_spi));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(struct sun6i_spi));
|
||||
if (!host) {
|
||||
dev_err(&pdev->dev, "Unable to allocate SPI Host\n");
|
||||
return -ENOMEM;
|
||||
|
|
@ -643,22 +643,18 @@ static int sun6i_spi_probe(struct platform_device *pdev)
|
|||
sspi = spi_controller_get_devdata(host);
|
||||
|
||||
sspi->base_addr = devm_platform_get_and_ioremap_resource(pdev, 0, &mem);
|
||||
if (IS_ERR(sspi->base_addr)) {
|
||||
ret = PTR_ERR(sspi->base_addr);
|
||||
goto err_free_host;
|
||||
}
|
||||
if (IS_ERR(sspi->base_addr))
|
||||
return PTR_ERR(sspi->base_addr);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
ret = -ENXIO;
|
||||
goto err_free_host;
|
||||
}
|
||||
if (irq < 0)
|
||||
return -ENXIO;
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, irq, sun6i_spi_handler,
|
||||
0, "sun6i-spi", sspi);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Cannot request IRQ\n");
|
||||
goto err_free_host;
|
||||
return ret;
|
||||
}
|
||||
|
||||
sspi->host = host;
|
||||
|
|
@ -679,15 +675,13 @@ static int sun6i_spi_probe(struct platform_device *pdev)
|
|||
sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
|
||||
if (IS_ERR(sspi->hclk)) {
|
||||
dev_err(&pdev->dev, "Unable to acquire AHB clock\n");
|
||||
ret = PTR_ERR(sspi->hclk);
|
||||
goto err_free_host;
|
||||
return PTR_ERR(sspi->hclk);
|
||||
}
|
||||
|
||||
sspi->mclk = devm_clk_get(&pdev->dev, "mod");
|
||||
if (IS_ERR(sspi->mclk)) {
|
||||
dev_err(&pdev->dev, "Unable to acquire module clock\n");
|
||||
ret = PTR_ERR(sspi->mclk);
|
||||
goto err_free_host;
|
||||
return PTR_ERR(sspi->mclk);
|
||||
}
|
||||
|
||||
init_completion(&sspi->done);
|
||||
|
|
@ -696,17 +690,14 @@ static int sun6i_spi_probe(struct platform_device *pdev)
|
|||
sspi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
|
||||
if (IS_ERR(sspi->rstc)) {
|
||||
dev_err(&pdev->dev, "Couldn't get reset controller\n");
|
||||
ret = PTR_ERR(sspi->rstc);
|
||||
goto err_free_host;
|
||||
return PTR_ERR(sspi->rstc);
|
||||
}
|
||||
|
||||
host->dma_tx = dma_request_chan(&pdev->dev, "tx");
|
||||
if (IS_ERR(host->dma_tx)) {
|
||||
/* Check tx to see if we need defer probing driver */
|
||||
if (PTR_ERR(host->dma_tx) == -EPROBE_DEFER) {
|
||||
ret = -EPROBE_DEFER;
|
||||
goto err_free_host;
|
||||
}
|
||||
if (PTR_ERR(host->dma_tx) == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
dev_warn(&pdev->dev, "Failed to request TX DMA channel\n");
|
||||
host->dma_tx = NULL;
|
||||
}
|
||||
|
|
@ -759,8 +750,7 @@ static int sun6i_spi_probe(struct platform_device *pdev)
|
|||
err_free_dma_tx:
|
||||
if (host->dma_tx)
|
||||
dma_release_channel(host->dma_tx);
|
||||
err_free_host:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -768,8 +758,6 @@ static void sun6i_spi_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
pm_runtime_force_suspend(&pdev->dev);
|
||||
|
|
@ -778,8 +766,6 @@ static void sun6i_spi_remove(struct platform_device *pdev)
|
|||
dma_release_channel(host->dma_tx);
|
||||
if (host->dma_rx)
|
||||
dma_release_channel(host->dma_rx);
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
static const struct sun6i_spi_cfg sun6i_a31_spi_cfg = {
|
||||
|
|
|
|||
|
|
@ -290,8 +290,7 @@ static void sp7021_spi_setup_clk(struct spi_controller *ctlr, struct spi_transfe
|
|||
div = max(2U, clk_rate / xfer->speed_hz);
|
||||
|
||||
clk_sel = (div / 2) - 1;
|
||||
pspim->xfer_conf &= ~SP7021_CLK_MASK;
|
||||
pspim->xfer_conf |= FIELD_PREP(SP7021_CLK_MASK, clk_sel);
|
||||
FIELD_MODIFY(SP7021_CLK_MASK, &pspim->xfer_conf, clk_sel);
|
||||
writel(pspim->xfer_conf, pspim->m_base + SP7021_SPI_CONFIG_REG);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -605,7 +605,7 @@ static int synquacer_spi_probe(struct platform_device *pdev)
|
|||
int ret;
|
||||
int rx_irq, tx_irq;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*sspi));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*sspi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -617,10 +617,8 @@ static int synquacer_spi_probe(struct platform_device *pdev)
|
|||
init_completion(&sspi->transfer_done);
|
||||
|
||||
sspi->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(sspi->regs)) {
|
||||
ret = PTR_ERR(sspi->regs);
|
||||
goto put_spi;
|
||||
}
|
||||
if (IS_ERR(sspi->regs))
|
||||
return PTR_ERR(sspi->regs);
|
||||
|
||||
sspi->clk_src_type = SYNQUACER_HSSPI_CLOCK_SRC_IHCLK; /* Default */
|
||||
device_property_read_u32(&pdev->dev, "socionext,ihclk-rate",
|
||||
|
|
@ -637,21 +635,19 @@ static int synquacer_spi_probe(struct platform_device *pdev)
|
|||
sspi->clk = devm_clk_get(sspi->dev, "iPCLK");
|
||||
} else {
|
||||
dev_err(&pdev->dev, "specified wrong clock source\n");
|
||||
ret = -EINVAL;
|
||||
goto put_spi;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (IS_ERR(sspi->clk)) {
|
||||
ret = dev_err_probe(&pdev->dev, PTR_ERR(sspi->clk),
|
||||
"clock not found\n");
|
||||
goto put_spi;
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(sspi->clk),
|
||||
"clock not found\n");
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(sspi->clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to enable clock (%d)\n",
|
||||
ret);
|
||||
goto put_spi;
|
||||
return ret;
|
||||
}
|
||||
|
||||
host->max_speed_hz = clk_get_rate(sspi->clk);
|
||||
|
|
@ -726,8 +722,6 @@ static int synquacer_spi_probe(struct platform_device *pdev)
|
|||
pm_runtime_disable(sspi->dev);
|
||||
disable_clk:
|
||||
clk_disable_unprepare(sspi->clk);
|
||||
put_spi:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -737,15 +731,11 @@ static void synquacer_spi_remove(struct platform_device *pdev)
|
|||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct synquacer_spi *sspi = spi_controller_get_devdata(host);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
pm_runtime_disable(sspi->dev);
|
||||
|
||||
clk_disable_unprepare(sspi->clk);
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
static int __maybe_unused synquacer_spi_suspend(struct device *dev)
|
||||
|
|
|
|||
|
|
@ -1302,7 +1302,7 @@ static int tegra_spi_probe(struct platform_device *pdev)
|
|||
int ret, spi_irq;
|
||||
int bus_num;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*tspi));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*tspi));
|
||||
if (!host) {
|
||||
dev_err(&pdev->dev, "host allocation failed\n");
|
||||
return -ENOMEM;
|
||||
|
|
@ -1336,36 +1336,31 @@ static int tegra_spi_probe(struct platform_device *pdev)
|
|||
tspi->soc_data = of_device_get_match_data(&pdev->dev);
|
||||
if (!tspi->soc_data) {
|
||||
dev_err(&pdev->dev, "unsupported tegra\n");
|
||||
ret = -ENODEV;
|
||||
goto exit_free_host;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
tspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r);
|
||||
if (IS_ERR(tspi->base)) {
|
||||
ret = PTR_ERR(tspi->base);
|
||||
goto exit_free_host;
|
||||
}
|
||||
if (IS_ERR(tspi->base))
|
||||
return PTR_ERR(tspi->base);
|
||||
|
||||
tspi->phys = r->start;
|
||||
|
||||
spi_irq = platform_get_irq(pdev, 0);
|
||||
if (spi_irq < 0) {
|
||||
ret = spi_irq;
|
||||
goto exit_free_host;
|
||||
}
|
||||
if (spi_irq < 0)
|
||||
return spi_irq;
|
||||
|
||||
tspi->irq = spi_irq;
|
||||
|
||||
tspi->clk = devm_clk_get(&pdev->dev, "spi");
|
||||
if (IS_ERR(tspi->clk)) {
|
||||
dev_err(&pdev->dev, "can not get clock\n");
|
||||
ret = PTR_ERR(tspi->clk);
|
||||
goto exit_free_host;
|
||||
return PTR_ERR(tspi->clk);
|
||||
}
|
||||
|
||||
tspi->rst = devm_reset_control_get_exclusive(&pdev->dev, "spi");
|
||||
if (IS_ERR(tspi->rst)) {
|
||||
dev_err(&pdev->dev, "can not get reset\n");
|
||||
ret = PTR_ERR(tspi->rst);
|
||||
goto exit_free_host;
|
||||
return PTR_ERR(tspi->rst);
|
||||
}
|
||||
|
||||
tspi->max_buf_size = SPI_FIFO_DEPTH << 2;
|
||||
|
|
@ -1373,7 +1368,7 @@ static int tegra_spi_probe(struct platform_device *pdev)
|
|||
|
||||
ret = tegra_spi_init_dma_param(tspi, true);
|
||||
if (ret < 0)
|
||||
goto exit_free_host;
|
||||
return ret;
|
||||
ret = tegra_spi_init_dma_param(tspi, false);
|
||||
if (ret < 0)
|
||||
goto exit_rx_dma_free;
|
||||
|
|
@ -1431,8 +1426,7 @@ static int tegra_spi_probe(struct platform_device *pdev)
|
|||
tegra_spi_deinit_dma_param(tspi, false);
|
||||
exit_rx_dma_free:
|
||||
tegra_spi_deinit_dma_param(tspi, true);
|
||||
exit_free_host:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1441,8 +1435,6 @@ static void tegra_spi_remove(struct platform_device *pdev)
|
|||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct tegra_spi_data *tspi = spi_controller_get_devdata(host);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
free_irq(tspi->irq, tspi);
|
||||
|
|
@ -1456,8 +1448,6 @@ static void tegra_spi_remove(struct platform_device *pdev)
|
|||
pm_runtime_disable(&pdev->dev);
|
||||
if (!pm_runtime_status_suspended(&pdev->dev))
|
||||
tegra_spi_runtime_suspend(&pdev->dev);
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
|
|||
|
|
@ -427,11 +427,9 @@ static int tegra_sflash_probe(struct platform_device *pdev)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*tsd));
|
||||
if (!host) {
|
||||
dev_err(&pdev->dev, "host allocation failed\n");
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*tsd));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* the spi->mode bits understood by this driver: */
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA;
|
||||
|
|
@ -450,14 +448,13 @@ static int tegra_sflash_probe(struct platform_device *pdev)
|
|||
host->max_speed_hz = 25000000; /* 25MHz */
|
||||
|
||||
tsd->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(tsd->base)) {
|
||||
ret = PTR_ERR(tsd->base);
|
||||
goto exit_free_host;
|
||||
}
|
||||
if (IS_ERR(tsd->base))
|
||||
return PTR_ERR(tsd->base);
|
||||
|
||||
ret = platform_get_irq(pdev, 0);
|
||||
if (ret < 0)
|
||||
goto exit_free_host;
|
||||
return ret;
|
||||
|
||||
tsd->irq = ret;
|
||||
|
||||
ret = request_irq(tsd->irq, tegra_sflash_isr, 0,
|
||||
|
|
@ -465,7 +462,7 @@ static int tegra_sflash_probe(struct platform_device *pdev)
|
|||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n",
|
||||
tsd->irq);
|
||||
goto exit_free_host;
|
||||
return ret;
|
||||
}
|
||||
|
||||
tsd->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
|
|
@ -518,8 +515,7 @@ static int tegra_sflash_probe(struct platform_device *pdev)
|
|||
tegra_sflash_runtime_suspend(&pdev->dev);
|
||||
exit_free_irq:
|
||||
free_irq(tsd->irq, tsd);
|
||||
exit_free_host:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -528,8 +524,6 @@ static void tegra_sflash_remove(struct platform_device *pdev)
|
|||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct tegra_sflash_data *tsd = spi_controller_get_devdata(host);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
free_irq(tsd->irq, tsd);
|
||||
|
|
@ -537,8 +531,6 @@ static void tegra_sflash_remove(struct platform_device *pdev)
|
|||
pm_runtime_disable(&pdev->dev);
|
||||
if (!pm_runtime_status_suspended(&pdev->dev))
|
||||
tegra_sflash_runtime_suspend(&pdev->dev);
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
|
|||
|
|
@ -226,11 +226,13 @@ struct tegra_qspi {
|
|||
struct completion xfer_completion;
|
||||
struct spi_transfer *curr_xfer;
|
||||
|
||||
struct device *rx_dma_dev;
|
||||
struct dma_chan *rx_dma_chan;
|
||||
u32 *rx_dma_buf;
|
||||
dma_addr_t rx_dma_phys;
|
||||
struct dma_async_tx_descriptor *rx_dma_desc;
|
||||
|
||||
struct device *tx_dma_dev;
|
||||
struct dma_chan *tx_dma_chan;
|
||||
u32 *tx_dma_buf;
|
||||
dma_addr_t tx_dma_phys;
|
||||
|
|
@ -574,15 +576,15 @@ static int tegra_qspi_dma_map_xfer(struct tegra_qspi *tqspi, struct spi_transfer
|
|||
len = DIV_ROUND_UP(tqspi->curr_dma_words * tqspi->bytes_per_word, 4) * 4;
|
||||
|
||||
if (t->tx_buf) {
|
||||
t->tx_dma = dma_map_single(tqspi->dev, (void *)tx_buf, len, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(tqspi->dev, t->tx_dma))
|
||||
t->tx_dma = dma_map_single(tqspi->tx_dma_dev, (void *)tx_buf, len, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(tqspi->tx_dma_dev, t->tx_dma))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (t->rx_buf) {
|
||||
t->rx_dma = dma_map_single(tqspi->dev, (void *)rx_buf, len, DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(tqspi->dev, t->rx_dma)) {
|
||||
dma_unmap_single(tqspi->dev, t->tx_dma, len, DMA_TO_DEVICE);
|
||||
t->rx_dma = dma_map_single(tqspi->rx_dma_dev, (void *)rx_buf, len, DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(tqspi->rx_dma_dev, t->rx_dma)) {
|
||||
dma_unmap_single(tqspi->tx_dma_dev, t->tx_dma, len, DMA_TO_DEVICE);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
|
@ -597,9 +599,9 @@ static void tegra_qspi_dma_unmap_xfer(struct tegra_qspi *tqspi, struct spi_trans
|
|||
len = DIV_ROUND_UP(tqspi->curr_dma_words * tqspi->bytes_per_word, 4) * 4;
|
||||
|
||||
if (t->tx_buf)
|
||||
dma_unmap_single(tqspi->dev, t->tx_dma, len, DMA_TO_DEVICE);
|
||||
dma_unmap_single(tqspi->tx_dma_dev, t->tx_dma, len, DMA_TO_DEVICE);
|
||||
if (t->rx_buf)
|
||||
dma_unmap_single(tqspi->dev, t->rx_dma, len, DMA_FROM_DEVICE);
|
||||
dma_unmap_single(tqspi->rx_dma_dev, t->rx_dma, len, DMA_FROM_DEVICE);
|
||||
}
|
||||
|
||||
static int tegra_qspi_start_dma_based_transfer(struct tegra_qspi *tqspi, struct spi_transfer *t)
|
||||
|
|
@ -745,7 +747,7 @@ static int tegra_qspi_start_cpu_based_transfer(struct tegra_qspi *qspi, struct s
|
|||
static void tegra_qspi_deinit_dma(struct tegra_qspi *tqspi)
|
||||
{
|
||||
if (tqspi->tx_dma_buf) {
|
||||
dma_free_coherent(tqspi->dev, tqspi->dma_buf_size,
|
||||
dma_free_coherent(tqspi->tx_dma_dev, tqspi->dma_buf_size,
|
||||
tqspi->tx_dma_buf, tqspi->tx_dma_phys);
|
||||
tqspi->tx_dma_buf = NULL;
|
||||
}
|
||||
|
|
@ -756,7 +758,7 @@ static void tegra_qspi_deinit_dma(struct tegra_qspi *tqspi)
|
|||
}
|
||||
|
||||
if (tqspi->rx_dma_buf) {
|
||||
dma_free_coherent(tqspi->dev, tqspi->dma_buf_size,
|
||||
dma_free_coherent(tqspi->rx_dma_dev, tqspi->dma_buf_size,
|
||||
tqspi->rx_dma_buf, tqspi->rx_dma_phys);
|
||||
tqspi->rx_dma_buf = NULL;
|
||||
}
|
||||
|
|
@ -782,6 +784,7 @@ static int tegra_qspi_init_dma(struct tegra_qspi *tqspi)
|
|||
}
|
||||
|
||||
tqspi->rx_dma_chan = dma_chan;
|
||||
tqspi->rx_dma_dev = dmaengine_get_dma_device(tqspi->rx_dma_chan);
|
||||
|
||||
dma_chan = dma_request_chan(tqspi->dev, "tx");
|
||||
if (IS_ERR(dma_chan)) {
|
||||
|
|
@ -790,15 +793,19 @@ static int tegra_qspi_init_dma(struct tegra_qspi *tqspi)
|
|||
}
|
||||
|
||||
tqspi->tx_dma_chan = dma_chan;
|
||||
tqspi->tx_dma_dev = dmaengine_get_dma_device(tqspi->tx_dma_chan);
|
||||
} else {
|
||||
if (!device_iommu_mapped(tqspi->dev)) {
|
||||
dev_warn(tqspi->dev,
|
||||
"IOMMU not enabled in device-tree, falling back to PIO mode\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
tqspi->rx_dma_dev = tqspi->dev;
|
||||
tqspi->tx_dma_dev = tqspi->dev;
|
||||
}
|
||||
|
||||
dma_buf = dma_alloc_coherent(tqspi->dev, tqspi->dma_buf_size, &dma_phys, GFP_KERNEL);
|
||||
dma_buf = dma_alloc_coherent(tqspi->rx_dma_dev, tqspi->dma_buf_size, &dma_phys, GFP_KERNEL);
|
||||
if (!dma_buf) {
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
|
|
@ -807,7 +814,7 @@ static int tegra_qspi_init_dma(struct tegra_qspi *tqspi)
|
|||
tqspi->rx_dma_buf = dma_buf;
|
||||
tqspi->rx_dma_phys = dma_phys;
|
||||
|
||||
dma_buf = dma_alloc_coherent(tqspi->dev, tqspi->dma_buf_size, &dma_phys, GFP_KERNEL);
|
||||
dma_buf = dma_alloc_coherent(tqspi->tx_dma_dev, tqspi->dma_buf_size, &dma_phys, GFP_KERNEL);
|
||||
if (!dma_buf) {
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
|
|
|
|||
|
|
@ -765,7 +765,7 @@ static int ti_qspi_probe(struct platform_device *pdev)
|
|||
int ret = 0, num_cs, irq;
|
||||
dma_cap_mask_t mask;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*qspi));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*qspi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -793,8 +793,7 @@ static int ti_qspi_probe(struct platform_device *pdev)
|
|||
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (r == NULL) {
|
||||
dev_err(&pdev->dev, "missing platform data\n");
|
||||
ret = -ENODEV;
|
||||
goto free_host;
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -812,28 +811,22 @@ static int ti_qspi_probe(struct platform_device *pdev)
|
|||
qspi->mmap_size = resource_size(res_mmap);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
ret = irq;
|
||||
goto free_host;
|
||||
}
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
mutex_init(&qspi->list_lock);
|
||||
|
||||
qspi->base = devm_ioremap_resource(&pdev->dev, r);
|
||||
if (IS_ERR(qspi->base)) {
|
||||
ret = PTR_ERR(qspi->base);
|
||||
goto free_host;
|
||||
}
|
||||
if (IS_ERR(qspi->base))
|
||||
return PTR_ERR(qspi->base);
|
||||
|
||||
|
||||
if (of_property_present(np, "syscon-chipselects")) {
|
||||
qspi->ctrl_base =
|
||||
syscon_regmap_lookup_by_phandle_args(np, "syscon-chipselects",
|
||||
1, &qspi->ctrl_reg);
|
||||
if (IS_ERR(qspi->ctrl_base)) {
|
||||
ret = PTR_ERR(qspi->ctrl_base);
|
||||
goto free_host;
|
||||
}
|
||||
if (IS_ERR(qspi->ctrl_base))
|
||||
return PTR_ERR(qspi->ctrl_base);
|
||||
}
|
||||
|
||||
qspi->fclk = devm_clk_get(&pdev->dev, "fck");
|
||||
|
|
@ -890,14 +883,16 @@ static int ti_qspi_probe(struct platform_device *pdev)
|
|||
qspi->current_cs = -1;
|
||||
|
||||
ret = spi_register_controller(host);
|
||||
if (!ret)
|
||||
return 0;
|
||||
if (ret)
|
||||
goto err_free_dma;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_dma:
|
||||
ti_qspi_dma_cleanup(qspi);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
free_host:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -905,16 +900,12 @@ static void ti_qspi_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct ti_qspi *qspi = platform_get_drvdata(pdev);
|
||||
|
||||
spi_controller_get(qspi->host);
|
||||
|
||||
spi_unregister_controller(qspi->host);
|
||||
|
||||
pm_runtime_put_sync(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
ti_qspi_dma_cleanup(qspi);
|
||||
|
||||
spi_controller_put(qspi->host);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops ti_qspi_pm_ops = {
|
||||
|
|
|
|||
|
|
@ -207,10 +207,10 @@ struct pch_pd_dev_save {
|
|||
};
|
||||
|
||||
static const struct pci_device_id pch_spi_pcidev_id[] = {
|
||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_GE_SPI), 1, },
|
||||
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_SPI), 2, },
|
||||
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_SPI), 1, },
|
||||
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_SPI), 1, },
|
||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_GE_SPI), .driver_data = 1 },
|
||||
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_SPI), .driver_data = 2 },
|
||||
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_SPI), .driver_data = 1 },
|
||||
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_SPI), .driver_data = 1 },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
@ -1406,8 +1406,6 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev)
|
|||
dev_dbg(&plat_dev->dev, "%s:[ch%d] irq=%d\n",
|
||||
__func__, plat_dev->id, board_dat->pdev->irq);
|
||||
|
||||
spi_controller_get(data->host);
|
||||
|
||||
spi_unregister_controller(data->host);
|
||||
|
||||
/* check for any pending messages; no action is taken if the queue
|
||||
|
|
|
|||
|
|
@ -184,14 +184,12 @@ static void uniphier_spi_set_transfer_size(struct spi_device *spi, int size)
|
|||
u32 val;
|
||||
|
||||
val = readl(priv->base + SSI_TXWDS);
|
||||
val &= ~(SSI_TXWDS_WDLEN_MASK | SSI_TXWDS_DTLEN_MASK);
|
||||
val |= FIELD_PREP(SSI_TXWDS_WDLEN_MASK, size);
|
||||
val |= FIELD_PREP(SSI_TXWDS_DTLEN_MASK, size);
|
||||
FIELD_MODIFY(SSI_TXWDS_WDLEN_MASK, &val, size);
|
||||
FIELD_MODIFY(SSI_TXWDS_DTLEN_MASK, &val, size);
|
||||
writel(val, priv->base + SSI_TXWDS);
|
||||
|
||||
val = readl(priv->base + SSI_RXWDS);
|
||||
val &= ~SSI_RXWDS_DTLEN_MASK;
|
||||
val |= FIELD_PREP(SSI_RXWDS_DTLEN_MASK, size);
|
||||
FIELD_MODIFY(SSI_RXWDS_DTLEN_MASK, &val, size);
|
||||
writel(val, priv->base + SSI_RXWDS);
|
||||
}
|
||||
|
||||
|
|
@ -308,9 +306,8 @@ static void uniphier_spi_set_fifo_threshold(struct uniphier_spi_priv *priv,
|
|||
u32 val;
|
||||
|
||||
val = readl(priv->base + SSI_FC);
|
||||
val &= ~(SSI_FC_TXFTH_MASK | SSI_FC_RXFTH_MASK);
|
||||
val |= FIELD_PREP(SSI_FC_TXFTH_MASK, SSI_FIFO_DEPTH - threshold);
|
||||
val |= FIELD_PREP(SSI_FC_RXFTH_MASK, threshold);
|
||||
FIELD_MODIFY(SSI_FC_TXFTH_MASK, &val, SSI_FIFO_DEPTH - threshold);
|
||||
FIELD_MODIFY(SSI_FC_RXFTH_MASK, &val, threshold);
|
||||
writel(val, priv->base + SSI_FC);
|
||||
}
|
||||
|
||||
|
|
@ -649,7 +646,7 @@ static int uniphier_spi_probe(struct platform_device *pdev)
|
|||
int irq;
|
||||
int ret;
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*priv));
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*priv));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -660,30 +657,26 @@ static int uniphier_spi_probe(struct platform_device *pdev)
|
|||
priv->is_save_param = false;
|
||||
|
||||
priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
if (IS_ERR(priv->base)) {
|
||||
ret = PTR_ERR(priv->base);
|
||||
goto out_host_put;
|
||||
}
|
||||
if (IS_ERR(priv->base))
|
||||
return PTR_ERR(priv->base);
|
||||
|
||||
priv->base_dma_addr = res->start;
|
||||
|
||||
priv->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(priv->clk)) {
|
||||
dev_err(&pdev->dev, "failed to get clock\n");
|
||||
ret = PTR_ERR(priv->clk);
|
||||
goto out_host_put;
|
||||
return PTR_ERR(priv->clk);
|
||||
}
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
ret = irq;
|
||||
goto out_host_put;
|
||||
}
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, irq, uniphier_spi_handler,
|
||||
0, "uniphier-spi", priv);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to request IRQ\n");
|
||||
goto out_host_put;
|
||||
return ret;
|
||||
}
|
||||
|
||||
init_completion(&priv->xfer_done);
|
||||
|
|
@ -710,10 +703,9 @@ static int uniphier_spi_probe(struct platform_device *pdev)
|
|||
|
||||
host->dma_tx = dma_request_chan(&pdev->dev, "tx");
|
||||
if (IS_ERR_OR_NULL(host->dma_tx)) {
|
||||
if (PTR_ERR(host->dma_tx) == -EPROBE_DEFER) {
|
||||
ret = -EPROBE_DEFER;
|
||||
goto out_host_put;
|
||||
}
|
||||
if (PTR_ERR(host->dma_tx) == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
host->dma_tx = NULL;
|
||||
dma_tx_burst = INT_MAX;
|
||||
} else {
|
||||
|
|
@ -762,8 +754,6 @@ static int uniphier_spi_probe(struct platform_device *pdev)
|
|||
host->dma_tx = NULL;
|
||||
}
|
||||
|
||||
out_host_put:
|
||||
spi_controller_put(host);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -771,16 +761,12 @@ static void uniphier_spi_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
|
||||
spi_controller_get(host);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
|
||||
if (host->dma_tx)
|
||||
dma_release_channel(host->dma_tx);
|
||||
if (host->dma_rx)
|
||||
dma_release_channel(host->dma_rx);
|
||||
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
static const struct of_device_id uniphier_spi_match[] = {
|
||||
|
|
|
|||
|
|
@ -377,7 +377,7 @@ static int wpcm_fiu_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
|||
struct wpcm_fiu_spi *fiu = spi_controller_get_devdata(desc->mem->spi->controller);
|
||||
int cs = spi_get_chipselect(desc->mem->spi, 0);
|
||||
|
||||
if (desc->info.op_tmpl.data.dir != SPI_MEM_DATA_IN)
|
||||
if (desc->info.op_tmpl->data.dir != SPI_MEM_DATA_IN)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -269,8 +269,8 @@ static int spi_xcomm_probe(struct i2c_client *i2c)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id spi_xcomm_ids[] = {
|
||||
{ "spi-xcomm" },
|
||||
{ },
|
||||
{ .name = "spi-xcomm" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, spi_xcomm_ids);
|
||||
|
||||
|
|
|
|||
|
|
@ -285,7 +285,11 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
|
|||
|
||||
if (use_irq) {
|
||||
xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
|
||||
wait_for_completion(&xspi->done);
|
||||
if (!wait_for_completion_timeout(&xspi->done, secs_to_jiffies(1))) {
|
||||
dev_err(&spi->dev, "SPI transfer timed out\n");
|
||||
xspi_init_hw(xspi);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
/* A transmit has just completed. Process received data
|
||||
* and check for more data to transmit. Always inhibit
|
||||
* the transmitter while the Isr refills the transmit
|
||||
|
|
@ -371,11 +375,18 @@ static int xilinx_spi_find_buffer_size(struct xilinx_spi *xspi)
|
|||
xspi->regs + XIPIF_V123B_RESETR_OFFSET);
|
||||
|
||||
/* Fill the Tx FIFO with as many words as possible */
|
||||
do {
|
||||
while (1) {
|
||||
xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET);
|
||||
sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
|
||||
if (sr & XSPI_SR_TX_FULL_MASK)
|
||||
break;
|
||||
|
||||
n_words++;
|
||||
} while (!(sr & XSPI_SR_TX_FULL_MASK));
|
||||
}
|
||||
|
||||
/* Handle the NO FIFO case separately */
|
||||
if (!n_words)
|
||||
return 1;
|
||||
|
||||
return n_words;
|
||||
}
|
||||
|
|
@ -515,8 +526,6 @@ static void xilinx_spi_remove(struct platform_device *pdev)
|
|||
xspi->write_fn(0, regs_base + XIPIF_V123B_IIER_OFFSET);
|
||||
/* Disable the global IPIF interrupt */
|
||||
xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET);
|
||||
|
||||
spi_controller_put(xspi->bitbang.ctlr);
|
||||
}
|
||||
|
||||
/* work with hotplug and coldplug */
|
||||
|
|
|
|||
|
|
@ -398,7 +398,7 @@ static int xlp_spi_probe(struct platform_device *pdev)
|
|||
|
||||
xspi->spi_clk = clk_get_rate(clk);
|
||||
|
||||
host = spi_alloc_host(&pdev->dev, 0);
|
||||
host = devm_spi_alloc_host(&pdev->dev, 0);
|
||||
if (!host) {
|
||||
dev_err(&pdev->dev, "could not alloc host\n");
|
||||
return -ENOMEM;
|
||||
|
|
@ -418,7 +418,6 @@ static int xlp_spi_probe(struct platform_device *pdev)
|
|||
err = devm_spi_register_controller(&pdev->dev, host);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "spi register host failed!\n");
|
||||
spi_controller_put(host);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -122,7 +122,6 @@ static void xtfpga_spi_remove(struct platform_device *pdev)
|
|||
struct xtfpga_spi *xspi = spi_controller_get_devdata(host);
|
||||
|
||||
spi_bitbang_stop(&xspi->bitbang);
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
MODULE_ALIAS("platform:" XTFPGA_SPI_NAME);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user