spi: Updates for v6.7
This is a very quiet release for SPI, we've got cleanups and minor fixes but only a few new driver specific features. The bulk of the changes in terms of diffstat are the cleanups, plus one bit of performance work for McSPI. - Conversions to use devm_clk_get_enabled() and to remove outdated terms for controller and device. - Device mode support for the Renesas CSI. - Cleanups and improvements to the device tree bindings aimed at making validation better. - PIO FIFO usage for the OMAP2 McSPI, improving performance. -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmU/r8kACgkQJNaLcl1U h9B+/Qf8C+skBk4ugBT/6YvJcA+SD9MiAezhJ+ap2noUVpqWI4sJnCHl5uXAt1s5 1nSZyi1T6XDcYkMtddboGrBL6Ht7nw1gJRnOi0lGrJWq09wAhiv5syxSjo5lDBX+ bbXayj7UD7WQqAPID57mM+CQF/DhDypx3B+qudG3doH0Mge3Iw+9BmAVCu+Z+LOE zq8wAPwxED1zwyL5zeNui3KmyATg0cxxYghocE+1SQY4MFq+94zYr3KaQCRg4PpC 6MLXwHRp4wwrwJ8va+RlIdIDUjKPTRyXSLJDEhjbNbjjf5SsD/JYV71pBqkA0O6i RbLcn6PwkbPmw5HMCY7qUi1CxJyybg== =NdkA -----END PGP SIGNATURE----- Merge tag 'spi-v6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi Pull spi updates from Mark Brown: "This is a very quiet release for SPI, we've got cleanups and minor fixes but only a few new driver specific features. The bulk of the changes in terms of diffstat are the cleanups, plus one bit of performance work for McSPI. - Conversions to use devm_clk_get_enabled() and to remove outdated terms for controller and device - Device mode support for the Renesas CSI - Cleanups and improvements to the device tree bindings aimed at making validation better - PIO FIFO usage for the OMAP2 McSPI, improving performance" * tag 'spi-v6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (75 commits) spi: omap2-mcspi: Add FIFO support without DMA spi: stm32: Explicitly include correct DT includes spi: Export acpi_spi_find_controller_by_adev() spi: nxp-fspi: use the correct ioremap function spi: Don't use flexible array in struct spi_message definition spi: bcm2835: add a sentinel at the end of the lookup array spi: spi-geni-qcom: Rename the label unmap_if_dma spi: rzv2m-csi: Add target mode support spi: renesas,rzv2m-csi: Add CSI (SPI) target related property spi: spidev: make spidev_class constant spi: mpc52xx-psc: Make mpc52xx_psc_spi_transfer_one_message() static spi: spi-cadence-quadspi: Fix missing unwind goto warnings spi: omap2-mcspi: Fix hardcoded reference clock spi: dt-bindings: Make "additionalProperties: true" explicit spi: at91-usart: Remove some dead code spi: dt-bindings: st,stm32-spi: Move "st,spi-midi-ns" to spi-peripheral-props.yaml spi: qup: Vote for interconnect bandwidth to DRAM spi: dt-bindings: qup: Document interconnects spi: qup: Parse OPP table for DVFS support spi: dt-bindings: qup: Document power-domains and OPP ...
This commit is contained in:
commit
34aac0a33d
@ -46,6 +46,8 @@ properties:
|
||||
patternProperties:
|
||||
"^.*@[0-9a-f]+":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
|
@ -68,6 +68,8 @@ properties:
|
||||
patternProperties:
|
||||
"^.*@[0-9a-f]+":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
|
@ -0,0 +1,61 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/spi/arm,pl022-peripheral-props.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Peripheral-specific properties for Arm PL022 SPI controller
|
||||
|
||||
maintainers:
|
||||
- Linus Walleij <linus.walleij@linaro.org>
|
||||
|
||||
select: false
|
||||
|
||||
properties:
|
||||
pl022,interface:
|
||||
description: SPI interface type
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum:
|
||||
- 0 # SPI
|
||||
- 1 # Texas Instruments Synchronous Serial Frame Format
|
||||
- 2 # Microwire (Half Duplex)
|
||||
|
||||
pl022,com-mode:
|
||||
description: Specifies the transfer mode
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum:
|
||||
- 0 # interrupt mode
|
||||
- 1 # polling mode
|
||||
- 2 # DMA mode
|
||||
default: 1
|
||||
|
||||
pl022,rx-level-trig:
|
||||
description: Rx FIFO watermark level
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 4
|
||||
|
||||
pl022,tx-level-trig:
|
||||
description: Tx FIFO watermark level
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 4
|
||||
|
||||
pl022,ctrl-len:
|
||||
description: Microwire interface - Control length
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0x03
|
||||
maximum: 0x1f
|
||||
|
||||
pl022,wait-state:
|
||||
description: Microwire interface - Wait state
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [0, 1]
|
||||
|
||||
pl022,duplex:
|
||||
description: Microwire interface - Full/Half duplex
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [0, 1]
|
||||
|
||||
additionalProperties: true
|
||||
...
|
@ -50,6 +50,7 @@ properties:
|
||||
patternProperties:
|
||||
"@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
spi-rx-bus-width:
|
||||
|
@ -44,9 +44,17 @@ properties:
|
||||
- const: tx
|
||||
- const: rx
|
||||
|
||||
interconnects:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
operating-points-v2: true
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@ -62,7 +70,9 @@ unevaluatedProperties: false
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-msm8996.h>
|
||||
#include <dt-bindings/interconnect/qcom,msm8996.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/power/qcom-rpmpd.h>
|
||||
|
||||
spi@7575000 {
|
||||
compatible = "qcom,spi-qup-v2.2.1";
|
||||
@ -76,6 +86,9 @@ examples:
|
||||
pinctrl-1 = <&blsp1_spi1_sleep>;
|
||||
dmas = <&blsp1_dma 12>, <&blsp1_dma 13>;
|
||||
dma-names = "tx", "rx";
|
||||
power-domains = <&rpmpd MSM8996_VDDCX>;
|
||||
operating-points-v2 = <&spi_opp_table>;
|
||||
interconnects = <&pnoc MASTER_BLSP_1 &bimc SLAVE_EBI_CH0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
@ -39,6 +39,12 @@ properties:
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
renesas,csi-no-ss:
|
||||
type: boolean
|
||||
description:
|
||||
The CSI Slave Selection (SS) pin won't be used to enable transmission and
|
||||
reception. Only available when in target mode.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
@ -50,6 +56,9 @@ required:
|
||||
- '#address-cells'
|
||||
- '#size-cells'
|
||||
|
||||
dependencies:
|
||||
renesas,csi-no-ss: [ spi-slave ]
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
|
@ -47,6 +47,8 @@ properties:
|
||||
patternProperties:
|
||||
"^flash@[0-3]$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
reg:
|
||||
minimum: 0
|
||||
|
@ -160,6 +160,8 @@ properties:
|
||||
patternProperties:
|
||||
"^.*@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
reg:
|
||||
minimum: 0
|
||||
|
@ -113,8 +113,14 @@ properties:
|
||||
minItems: 2
|
||||
maxItems: 4
|
||||
|
||||
st,spi-midi-ns:
|
||||
description: |
|
||||
Only for STM32H7, (Master Inter-Data Idleness) minimum time
|
||||
delay in nanoseconds inserted between two consecutive data frames.
|
||||
|
||||
# The controller specific properties go here.
|
||||
allOf:
|
||||
- $ref: arm,pl022-peripheral-props.yaml#
|
||||
- $ref: cdns,qspi-nor-peripheral-props.yaml#
|
||||
- $ref: samsung,spi-peripheral-props.yaml#
|
||||
- $ref: nvidia,tegra210-quad-peripheral-props.yaml#
|
||||
|
@ -74,57 +74,6 @@ properties:
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
patternProperties:
|
||||
"^[a-zA-Z][a-zA-Z0-9,+\\-._]{0,63}@[0-9a-f]+$":
|
||||
type: object
|
||||
# SPI slave nodes must be children of the SPI master node and can
|
||||
# contain the following properties.
|
||||
properties:
|
||||
pl022,interface:
|
||||
description: SPI interface type
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum:
|
||||
- 0 # SPI
|
||||
- 1 # Texas Instruments Synchronous Serial Frame Format
|
||||
- 2 # Microwire (Half Duplex)
|
||||
|
||||
pl022,com-mode:
|
||||
description: Specifies the transfer mode
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum:
|
||||
- 0 # interrupt mode
|
||||
- 1 # polling mode
|
||||
- 2 # DMA mode
|
||||
default: 1
|
||||
|
||||
pl022,rx-level-trig:
|
||||
description: Rx FIFO watermark level
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 4
|
||||
|
||||
pl022,tx-level-trig:
|
||||
description: Tx FIFO watermark level
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 4
|
||||
|
||||
pl022,ctrl-len:
|
||||
description: Microwire interface - Control length
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0x03
|
||||
maximum: 0x1f
|
||||
|
||||
pl022,wait-state:
|
||||
description: Microwire interface - Wait state
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [0, 1]
|
||||
|
||||
pl022,duplex:
|
||||
description: Microwire interface - Full/Half duplex
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [0, 1]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -18,15 +18,6 @@ maintainers:
|
||||
|
||||
allOf:
|
||||
- $ref: spi-controller.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: st,stm32f4-spi
|
||||
|
||||
then:
|
||||
properties:
|
||||
st,spi-midi-ns: false
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
@ -59,17 +50,6 @@ properties:
|
||||
- const: rx
|
||||
- const: tx
|
||||
|
||||
patternProperties:
|
||||
"^[a-zA-Z][a-zA-Z0-9,+\\-._]{0,63}@[0-9a-f]+$":
|
||||
type: object
|
||||
# SPI slave nodes must be children of the SPI master node and can
|
||||
# contain the following properties.
|
||||
properties:
|
||||
st,spi-midi-ns:
|
||||
description: |
|
||||
Only for STM32H7, (Master Inter-Data Idleness) minimum time
|
||||
delay in nanoseconds inserted between two consecutive data frames.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -862,7 +862,8 @@ config SPI_RZV2M_CSI
|
||||
tristate "Renesas RZ/V2M CSI controller"
|
||||
depends on ARCH_RENESAS || COMPILE_TEST
|
||||
help
|
||||
SPI driver for Renesas RZ/V2M Clocked Serial Interface (CSI)
|
||||
SPI driver for Renesas RZ/V2M Clocked Serial Interface (CSI).
|
||||
CSI supports both SPI host and SPI target roles.
|
||||
|
||||
config SPI_QCOM_QSPI
|
||||
tristate "QTI QSPI controller"
|
||||
|
@ -168,27 +168,21 @@ static int ar934x_spi_probe(struct platform_device *pdev)
|
||||
struct ar934x_spi *sp;
|
||||
void __iomem *base;
|
||||
struct clk *clk;
|
||||
int ret;
|
||||
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
clk = devm_clk_get(&pdev->dev, NULL);
|
||||
clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(clk)) {
|
||||
dev_err(&pdev->dev, "failed to get clock\n");
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*sp));
|
||||
if (!ctlr) {
|
||||
dev_info(&pdev->dev, "failed to allocate spi controller\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_clk_disable;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* disable flash mapping and expose spi controller registers */
|
||||
@ -212,25 +206,15 @@ static int ar934x_spi_probe(struct platform_device *pdev)
|
||||
sp->clk_freq = clk_get_rate(clk);
|
||||
sp->ctlr = ctlr;
|
||||
|
||||
ret = spi_register_controller(ctlr);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
err_clk_disable:
|
||||
clk_disable_unprepare(clk);
|
||||
return ret;
|
||||
return spi_register_controller(ctlr);
|
||||
}
|
||||
|
||||
static void ar934x_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_controller *ctlr;
|
||||
struct ar934x_spi *sp;
|
||||
|
||||
ctlr = dev_get_drvdata(&pdev->dev);
|
||||
sp = spi_controller_get_devdata(ctlr);
|
||||
|
||||
spi_unregister_controller(ctlr);
|
||||
clk_disable_unprepare(sp->clk);
|
||||
}
|
||||
|
||||
static struct platform_driver ar934x_spi_driver = {
|
||||
|
@ -865,18 +865,12 @@ static int a3700_spi_probe(struct platform_device *pdev)
|
||||
|
||||
init_completion(&spi->done);
|
||||
|
||||
spi->clk = devm_clk_get(dev, NULL);
|
||||
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;
|
||||
}
|
||||
|
||||
ret = clk_prepare(spi->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "could not prepare clk: %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
host->max_speed_hz = min_t(unsigned long, A3700_SPI_MAX_SPEED_HZ,
|
||||
clk_get_rate(spi->clk));
|
||||
host->min_speed_hz = DIV_ROUND_UP(clk_get_rate(spi->clk),
|
||||
@ -888,40 +882,29 @@ static int a3700_spi_probe(struct platform_device *pdev)
|
||||
dev_name(dev), host);
|
||||
if (ret) {
|
||||
dev_err(dev, "could not request IRQ: %d\n", ret);
|
||||
goto error_clk;
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = devm_spi_register_controller(dev, host);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to register host\n");
|
||||
goto error_clk;
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_clk:
|
||||
clk_unprepare(spi->clk);
|
||||
error:
|
||||
spi_controller_put(host);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void a3700_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct a3700_spi *spi = spi_controller_get_devdata(host);
|
||||
|
||||
clk_unprepare(spi->clk);
|
||||
}
|
||||
|
||||
static struct platform_driver a3700_spi_driver = {
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.of_match_table = of_match_ptr(a3700_spi_dt_ids),
|
||||
},
|
||||
.probe = a3700_spi_probe,
|
||||
.remove_new = a3700_spi_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(a3700_spi_driver);
|
||||
|
@ -748,7 +748,7 @@ static int aspeed_spi_probe(struct platform_device *pdev)
|
||||
aspi->ahb_window_size = resource_size(res);
|
||||
aspi->ahb_base_phy = res->start;
|
||||
|
||||
aspi->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
aspi->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(aspi->clk)) {
|
||||
dev_err(dev, "missing clock\n");
|
||||
return PTR_ERR(aspi->clk);
|
||||
@ -760,12 +760,6 @@ static int aspeed_spi_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(aspi->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "can not enable the clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* IRQ is for DMA, which the driver doesn't support yet */
|
||||
|
||||
ctlr->mode_bits = SPI_RX_DUAL | SPI_TX_DUAL | data->mode_bits;
|
||||
@ -777,14 +771,9 @@ static int aspeed_spi_probe(struct platform_device *pdev)
|
||||
ctlr->dev.of_node = dev->of_node;
|
||||
|
||||
ret = devm_spi_register_controller(dev, ctlr);
|
||||
if (ret) {
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "spi_register_controller failed\n");
|
||||
goto disable_clk;
|
||||
}
|
||||
return 0;
|
||||
|
||||
disable_clk:
|
||||
clk_disable_unprepare(aspi->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -793,7 +782,6 @@ static void aspeed_spi_remove(struct platform_device *pdev)
|
||||
struct aspeed_spi *aspi = platform_get_drvdata(pdev);
|
||||
|
||||
aspeed_spi_enable(aspi, false);
|
||||
clk_disable_unprepare(aspi->clk);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -132,28 +132,14 @@ static int at91_usart_spi_configure_dma(struct spi_controller *ctlr,
|
||||
dma_cap_set(DMA_SLAVE, mask);
|
||||
|
||||
ctlr->dma_tx = dma_request_chan(dev, "tx");
|
||||
if (IS_ERR_OR_NULL(ctlr->dma_tx)) {
|
||||
if (IS_ERR(ctlr->dma_tx)) {
|
||||
err = PTR_ERR(ctlr->dma_tx);
|
||||
goto at91_usart_spi_error_clear;
|
||||
}
|
||||
|
||||
dev_dbg(dev,
|
||||
"DMA TX channel not available, SPI unable to use DMA\n");
|
||||
err = -EBUSY;
|
||||
if (IS_ERR(ctlr->dma_tx)) {
|
||||
err = PTR_ERR(ctlr->dma_tx);
|
||||
goto at91_usart_spi_error_clear;
|
||||
}
|
||||
|
||||
ctlr->dma_rx = dma_request_chan(dev, "rx");
|
||||
if (IS_ERR_OR_NULL(ctlr->dma_rx)) {
|
||||
if (IS_ERR(ctlr->dma_rx)) {
|
||||
err = PTR_ERR(ctlr->dma_rx);
|
||||
goto at91_usart_spi_error;
|
||||
}
|
||||
|
||||
dev_dbg(dev,
|
||||
"DMA RX channel not available, SPI unable to use DMA\n");
|
||||
err = -EBUSY;
|
||||
if (IS_ERR(ctlr->dma_rx)) {
|
||||
err = PTR_ERR(ctlr->dma_rx);
|
||||
goto at91_usart_spi_error;
|
||||
}
|
||||
|
||||
|
@ -200,20 +200,16 @@ static int ath79_spi_probe(struct platform_device *pdev)
|
||||
goto err_put_host;
|
||||
}
|
||||
|
||||
sp->clk = devm_clk_get(&pdev->dev, "ahb");
|
||||
sp->clk = devm_clk_get_enabled(&pdev->dev, "ahb");
|
||||
if (IS_ERR(sp->clk)) {
|
||||
ret = PTR_ERR(sp->clk);
|
||||
goto err_put_host;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(sp->clk);
|
||||
if (ret)
|
||||
goto err_put_host;
|
||||
|
||||
rate = DIV_ROUND_UP(clk_get_rate(sp->clk), MHZ);
|
||||
if (!rate) {
|
||||
ret = -EINVAL;
|
||||
goto err_clk_disable;
|
||||
goto err_put_host;
|
||||
}
|
||||
|
||||
sp->rrw_delay = ATH79_SPI_RRW_DELAY_FACTOR / rate;
|
||||
@ -229,8 +225,6 @@ static int ath79_spi_probe(struct platform_device *pdev)
|
||||
|
||||
err_disable:
|
||||
ath79_spi_disable(sp);
|
||||
err_clk_disable:
|
||||
clk_disable_unprepare(sp->clk);
|
||||
err_put_host:
|
||||
spi_controller_put(host);
|
||||
|
||||
@ -243,7 +237,6 @@ static void ath79_spi_remove(struct platform_device *pdev)
|
||||
|
||||
spi_bitbang_stop(&sp->bitbang);
|
||||
ath79_spi_disable(sp);
|
||||
clk_disable_unprepare(sp->clk);
|
||||
spi_controller_put(sp->bitbang.master);
|
||||
}
|
||||
|
||||
|
@ -485,30 +485,22 @@ static int spi_engine_probe(struct platform_device *pdev)
|
||||
|
||||
spin_lock_init(&spi_engine->lock);
|
||||
|
||||
spi_engine->clk = devm_clk_get(&pdev->dev, "s_axi_aclk");
|
||||
spi_engine->clk = devm_clk_get_enabled(&pdev->dev, "s_axi_aclk");
|
||||
if (IS_ERR(spi_engine->clk)) {
|
||||
ret = PTR_ERR(spi_engine->clk);
|
||||
goto err_put_host;
|
||||
}
|
||||
|
||||
spi_engine->ref_clk = devm_clk_get(&pdev->dev, "spi_clk");
|
||||
spi_engine->ref_clk = devm_clk_get_enabled(&pdev->dev, "spi_clk");
|
||||
if (IS_ERR(spi_engine->ref_clk)) {
|
||||
ret = PTR_ERR(spi_engine->ref_clk);
|
||||
goto err_put_host;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(spi_engine->clk);
|
||||
if (ret)
|
||||
goto err_put_host;
|
||||
|
||||
ret = clk_prepare_enable(spi_engine->ref_clk);
|
||||
if (ret)
|
||||
goto err_clk_disable;
|
||||
|
||||
spi_engine->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(spi_engine->base)) {
|
||||
ret = PTR_ERR(spi_engine->base);
|
||||
goto err_ref_clk_disable;
|
||||
goto err_put_host;
|
||||
}
|
||||
|
||||
version = readl(spi_engine->base + SPI_ENGINE_REG_VERSION);
|
||||
@ -518,7 +510,7 @@ static int spi_engine_probe(struct platform_device *pdev)
|
||||
SPI_ENGINE_VERSION_MINOR(version),
|
||||
SPI_ENGINE_VERSION_PATCH(version));
|
||||
ret = -ENODEV;
|
||||
goto err_ref_clk_disable;
|
||||
goto err_put_host;
|
||||
}
|
||||
|
||||
writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_RESET);
|
||||
@ -527,7 +519,7 @@ static int spi_engine_probe(struct platform_device *pdev)
|
||||
|
||||
ret = request_irq(irq, spi_engine_irq, 0, pdev->name, host);
|
||||
if (ret)
|
||||
goto err_ref_clk_disable;
|
||||
goto err_put_host;
|
||||
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_3WIRE;
|
||||
@ -545,10 +537,6 @@ static int spi_engine_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
err_free_irq:
|
||||
free_irq(irq, host);
|
||||
err_ref_clk_disable:
|
||||
clk_disable_unprepare(spi_engine->ref_clk);
|
||||
err_clk_disable:
|
||||
clk_disable_unprepare(spi_engine->clk);
|
||||
err_put_host:
|
||||
spi_controller_put(host);
|
||||
return ret;
|
||||
@ -569,9 +557,6 @@ static void spi_engine_remove(struct platform_device *pdev)
|
||||
writel_relaxed(0xff, spi_engine->base + SPI_ENGINE_REG_INT_PENDING);
|
||||
writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_INT_ENABLE);
|
||||
writel_relaxed(0x01, spi_engine->base + SPI_ENGINE_REG_RESET);
|
||||
|
||||
clk_disable_unprepare(spi_engine->ref_clk);
|
||||
clk_disable_unprepare(spi_engine->clk);
|
||||
}
|
||||
|
||||
static const struct of_device_id spi_engine_match_table[] = {
|
||||
|
@ -11,6 +11,7 @@
|
||||
* spi-atmel.c, Copyright (C) 2006 Atmel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/debugfs.h>
|
||||
@ -26,9 +27,10 @@
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/gpio/machine.h> /* FIXME: using chip internals */
|
||||
#include <linux/gpio/driver.h> /* FIXME: using chip internals */
|
||||
#include <linux/gpio/machine.h> /* FIXME: using GPIO lookup tables */
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
/* SPI register offsets */
|
||||
@ -83,6 +85,7 @@ MODULE_PARM_DESC(polling_limit_us,
|
||||
* struct bcm2835_spi - BCM2835 SPI controller
|
||||
* @regs: base address of register map
|
||||
* @clk: core clock, divided to calculate serial clock
|
||||
* @cs_gpio: chip-select GPIO descriptor
|
||||
* @clk_hz: core clock cached speed
|
||||
* @irq: interrupt, signals TX FIFO empty or RX FIFO ¾ full
|
||||
* @tfr: SPI transfer currently processed
|
||||
@ -117,6 +120,7 @@ MODULE_PARM_DESC(polling_limit_us,
|
||||
struct bcm2835_spi {
|
||||
void __iomem *regs;
|
||||
struct clk *clk;
|
||||
struct gpio_desc *cs_gpio;
|
||||
unsigned long clk_hz;
|
||||
int irq;
|
||||
struct spi_transfer *tfr;
|
||||
@ -1156,15 +1160,11 @@ static void bcm2835_spi_handle_err(struct spi_controller *ctlr,
|
||||
bcm2835_spi_reset_hw(bs);
|
||||
}
|
||||
|
||||
static int chip_match_name(struct gpio_chip *chip, void *data)
|
||||
{
|
||||
return !strcmp(chip->label, data);
|
||||
}
|
||||
|
||||
static void bcm2835_spi_cleanup(struct spi_device *spi)
|
||||
{
|
||||
struct bcm2835_spidev *target = spi_get_ctldata(spi);
|
||||
struct spi_controller *ctlr = spi->controller;
|
||||
struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
|
||||
|
||||
if (target->clear_rx_desc)
|
||||
dmaengine_desc_free(target->clear_rx_desc);
|
||||
@ -1175,6 +1175,9 @@ static void bcm2835_spi_cleanup(struct spi_device *spi)
|
||||
sizeof(u32),
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
gpiod_put(bs->cs_gpio);
|
||||
spi_set_csgpiod(spi, 0, NULL);
|
||||
|
||||
kfree(target);
|
||||
}
|
||||
|
||||
@ -1221,7 +1224,7 @@ static int bcm2835_spi_setup(struct spi_device *spi)
|
||||
struct spi_controller *ctlr = spi->controller;
|
||||
struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
|
||||
struct bcm2835_spidev *target = spi_get_ctldata(spi);
|
||||
struct gpio_chip *chip;
|
||||
struct gpiod_lookup_table *lookup __free(kfree) = NULL;
|
||||
int ret;
|
||||
u32 cs;
|
||||
|
||||
@ -1288,29 +1291,36 @@ static int bcm2835_spi_setup(struct spi_device *spi)
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate native CS to GPIO
|
||||
* TODO: The code below is a slightly better alternative to the utter
|
||||
* abuse of the GPIO API that I found here before. It creates a
|
||||
* temporary lookup table, assigns it to the SPI device, gets the GPIO
|
||||
* descriptor and then releases the lookup table.
|
||||
*
|
||||
* FIXME: poking around in the gpiolib internals like this is
|
||||
* not very good practice. Find a way to locate the real problem
|
||||
* and fix it. Why is the GPIO descriptor in spi->cs_gpiod
|
||||
* sometimes not assigned correctly? Erroneous device trees?
|
||||
* More on the problem that it addresses:
|
||||
* https://www.spinics.net/lists/linux-gpio/msg36218.html
|
||||
*/
|
||||
|
||||
/* get the gpio chip for the base */
|
||||
chip = gpiochip_find("pinctrl-bcm2835", chip_match_name);
|
||||
if (!chip)
|
||||
return 0;
|
||||
|
||||
spi_set_csgpiod(spi, 0, gpiochip_request_own_desc(chip,
|
||||
8 - (spi_get_chipselect(spi, 0)),
|
||||
DRV_NAME,
|
||||
GPIO_LOOKUP_FLAGS_DEFAULT,
|
||||
GPIOD_OUT_LOW));
|
||||
if (IS_ERR(spi_get_csgpiod(spi, 0))) {
|
||||
ret = PTR_ERR(spi_get_csgpiod(spi, 0));
|
||||
lookup = kzalloc(struct_size(lookup, table, 2), GFP_KERNEL);
|
||||
if (!lookup) {
|
||||
ret = -ENOMEM;
|
||||
goto err_cleanup;
|
||||
}
|
||||
|
||||
lookup->dev_id = dev_name(&spi->dev);
|
||||
lookup->table[0] = GPIO_LOOKUP("pinctrl-bcm2835",
|
||||
8 - (spi_get_chipselect(spi, 0)),
|
||||
"cs", GPIO_LOOKUP_FLAGS_DEFAULT);
|
||||
|
||||
gpiod_add_lookup_table(lookup);
|
||||
|
||||
bs->cs_gpio = gpiod_get(&spi->dev, "cs", GPIOD_OUT_LOW);
|
||||
gpiod_remove_lookup_table(lookup);
|
||||
if (IS_ERR(bs->cs_gpio)) {
|
||||
ret = PTR_ERR(bs->cs_gpio);
|
||||
goto err_cleanup;
|
||||
}
|
||||
|
||||
spi_set_csgpiod(spi, 0, bs->cs_gpio);
|
||||
|
||||
/* and set up the "mode" and level */
|
||||
dev_info(&spi->dev, "setting up native-CS%i to use GPIO\n",
|
||||
spi_get_chipselect(spi, 0));
|
||||
@ -1352,7 +1362,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(bs->regs))
|
||||
return PTR_ERR(bs->regs);
|
||||
|
||||
bs->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
bs->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(bs->clk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(bs->clk),
|
||||
"could not get clk\n");
|
||||
@ -1363,14 +1373,11 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
|
||||
if (bs->irq < 0)
|
||||
return bs->irq;
|
||||
|
||||
err = clk_prepare_enable(bs->clk);
|
||||
if (err)
|
||||
return err;
|
||||
bs->clk_hz = clk_get_rate(bs->clk);
|
||||
|
||||
err = bcm2835_dma_init(ctlr, &pdev->dev, bs);
|
||||
if (err)
|
||||
goto out_clk_disable;
|
||||
return err;
|
||||
|
||||
/* initialise the hardware with the default polarities */
|
||||
bcm2835_wr(bs, BCM2835_SPI_CS,
|
||||
@ -1396,8 +1403,6 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
|
||||
|
||||
out_dma_release:
|
||||
bcm2835_dma_release(ctlr, bs);
|
||||
out_clk_disable:
|
||||
clk_disable_unprepare(bs->clk);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1415,8 +1420,6 @@ static void bcm2835_spi_remove(struct platform_device *pdev)
|
||||
/* Clear FIFOs, and disable the HW block */
|
||||
bcm2835_wr(bs, BCM2835_SPI_CS,
|
||||
BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
|
||||
|
||||
clk_disable_unprepare(bs->clk);
|
||||
}
|
||||
|
||||
static const struct of_device_id bcm2835_spi_match[] = {
|
||||
|
@ -512,7 +512,7 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(bs->regs))
|
||||
return PTR_ERR(bs->regs);
|
||||
|
||||
bs->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
bs->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(bs->clk)) {
|
||||
err = PTR_ERR(bs->clk);
|
||||
dev_err(&pdev->dev, "could not get clk: %d\n", err);
|
||||
@ -523,19 +523,11 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
|
||||
if (bs->irq < 0)
|
||||
return bs->irq;
|
||||
|
||||
/* this also enables the HW block */
|
||||
err = clk_prepare_enable(bs->clk);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "could not prepare clock: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* just checking if the clock returns a sane value */
|
||||
clk_hz = clk_get_rate(bs->clk);
|
||||
if (!clk_hz) {
|
||||
dev_err(&pdev->dev, "clock returns 0 Hz\n");
|
||||
err = -ENODEV;
|
||||
goto out_clk_disable;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* reset SPI-HW block */
|
||||
@ -547,22 +539,18 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
|
||||
dev_name(&pdev->dev), host);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
|
||||
goto out_clk_disable;
|
||||
return err;
|
||||
}
|
||||
|
||||
err = spi_register_controller(host);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "could not register SPI host: %d\n", err);
|
||||
goto out_clk_disable;
|
||||
return err;
|
||||
}
|
||||
|
||||
bcm2835aux_debugfs_create(bs, dev_name(&pdev->dev));
|
||||
|
||||
return 0;
|
||||
|
||||
out_clk_disable:
|
||||
clk_disable_unprepare(bs->clk);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void bcm2835aux_spi_remove(struct platform_device *pdev)
|
||||
@ -575,9 +563,6 @@ static void bcm2835aux_spi_remove(struct platform_device *pdev)
|
||||
spi_unregister_controller(host);
|
||||
|
||||
bcm2835aux_spi_reset_hw(bs);
|
||||
|
||||
/* disable the HW block by releasing the clock */
|
||||
clk_disable_unprepare(bs->clk);
|
||||
}
|
||||
|
||||
static const struct of_device_id bcm2835aux_spi_match[] = {
|
||||
|
@ -116,6 +116,9 @@ struct cqspi_driver_platdata {
|
||||
#define CQSPI_TIMEOUT_MS 500
|
||||
#define CQSPI_READ_TIMEOUT_MS 10
|
||||
|
||||
/* Runtime_pm autosuspend delay */
|
||||
#define CQSPI_AUTOSUSPEND_TIMEOUT 2000
|
||||
|
||||
#define CQSPI_DUMMY_CLKS_PER_BYTE 8
|
||||
#define CQSPI_DUMMY_BYTES_MAX 4
|
||||
#define CQSPI_DUMMY_CLKS_MAX 31
|
||||
@ -1407,8 +1410,20 @@ static int cqspi_mem_process(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||
static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||
{
|
||||
int ret;
|
||||
struct cqspi_st *cqspi = spi_master_get_devdata(mem->spi->master);
|
||||
struct device *dev = &cqspi->pdev->dev;
|
||||
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret) {
|
||||
dev_err(&mem->spi->dev, "resume failed with %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = cqspi_mem_process(mem, op);
|
||||
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
if (ret)
|
||||
dev_err(&mem->spi->dev, "operation failed with %d\n", ret);
|
||||
|
||||
@ -1753,10 +1768,10 @@ static int cqspi_probe(struct platform_device *pdev)
|
||||
if (irq < 0)
|
||||
return -ENXIO;
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret < 0)
|
||||
goto probe_pm_failed;
|
||||
ret = pm_runtime_set_active(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
ret = clk_prepare_enable(cqspi->clk);
|
||||
if (ret) {
|
||||
@ -1862,21 +1877,32 @@ static int cqspi_probe(struct platform_device *pdev)
|
||||
goto probe_setup_failed;
|
||||
}
|
||||
|
||||
ret = devm_pm_runtime_enable(dev);
|
||||
if (ret) {
|
||||
if (cqspi->rx_chan)
|
||||
dma_release_channel(cqspi->rx_chan);
|
||||
goto probe_setup_failed;
|
||||
}
|
||||
|
||||
pm_runtime_set_autosuspend_delay(dev, CQSPI_AUTOSUSPEND_TIMEOUT);
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_get_noresume(dev);
|
||||
|
||||
ret = spi_register_controller(host);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register SPI ctlr %d\n", ret);
|
||||
goto probe_setup_failed;
|
||||
}
|
||||
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return 0;
|
||||
probe_setup_failed:
|
||||
cqspi_controller_enable(cqspi, 0);
|
||||
probe_reset_failed:
|
||||
clk_disable_unprepare(cqspi->clk);
|
||||
probe_clk_failed:
|
||||
pm_runtime_put_sync(dev);
|
||||
probe_pm_failed:
|
||||
pm_runtime_disable(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1928,7 +1954,8 @@ static int cqspi_resume(struct device *dev)
|
||||
return spi_controller_resume(host);
|
||||
}
|
||||
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(cqspi_dev_pm_ops, cqspi_suspend, cqspi_resume);
|
||||
static DEFINE_RUNTIME_DEV_PM_OPS(cqspi_dev_pm_ops, cqspi_suspend,
|
||||
cqspi_resume, NULL);
|
||||
|
||||
static const struct cqspi_driver_platdata cdns_qspi = {
|
||||
.quirks = CQSPI_DISABLE_DAC_MODE,
|
||||
@ -2012,7 +2039,7 @@ static struct platform_driver cqspi_platform_driver = {
|
||||
.remove_new = cqspi_remove,
|
||||
.driver = {
|
||||
.name = CQSPI_NAME,
|
||||
.pm = &cqspi_dev_pm_ops,
|
||||
.pm = pm_ptr(&cqspi_dev_pm_ops),
|
||||
.of_match_table = cqspi_dt_ids,
|
||||
},
|
||||
};
|
||||
|
@ -581,31 +581,19 @@ static int cdns_spi_probe(struct platform_device *pdev)
|
||||
goto remove_ctlr;
|
||||
}
|
||||
|
||||
xspi->pclk = devm_clk_get(&pdev->dev, "pclk");
|
||||
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;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(xspi->pclk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Unable to enable APB clock.\n");
|
||||
goto remove_ctlr;
|
||||
}
|
||||
|
||||
if (!spi_controller_is_target(ctlr)) {
|
||||
xspi->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
|
||||
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 clk_dis_apb;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(xspi->ref_clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Unable to enable device clock.\n");
|
||||
goto clk_dis_apb;
|
||||
goto remove_ctlr;
|
||||
}
|
||||
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
@ -679,10 +667,7 @@ clk_dis_all:
|
||||
if (!spi_controller_is_target(ctlr)) {
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
clk_disable_unprepare(xspi->ref_clk);
|
||||
}
|
||||
clk_dis_apb:
|
||||
clk_disable_unprepare(xspi->pclk);
|
||||
remove_ctlr:
|
||||
spi_controller_put(ctlr);
|
||||
return ret;
|
||||
@ -703,8 +688,6 @@ static void cdns_spi_remove(struct platform_device *pdev)
|
||||
|
||||
cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_DISABLE);
|
||||
|
||||
clk_disable_unprepare(xspi->ref_clk);
|
||||
clk_disable_unprepare(xspi->pclk);
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
|
@ -49,16 +49,12 @@ static int thunderx_spi_probe(struct pci_dev *pdev,
|
||||
p->regs.tx = 0x1010;
|
||||
p->regs.data = 0x1080;
|
||||
|
||||
p->clk = devm_clk_get(dev, NULL);
|
||||
p->clk = devm_clk_get_enabled(dev, NULL);
|
||||
if (IS_ERR(p->clk)) {
|
||||
ret = PTR_ERR(p->clk);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(p->clk);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
p->sys_freq = clk_get_rate(p->clk);
|
||||
if (!p->sys_freq)
|
||||
p->sys_freq = SYS_FREQ_DEFAULT;
|
||||
@ -82,7 +78,6 @@ static int thunderx_spi_probe(struct pci_dev *pdev,
|
||||
return 0;
|
||||
|
||||
error:
|
||||
clk_disable_unprepare(p->clk);
|
||||
pci_release_regions(pdev);
|
||||
spi_controller_put(host);
|
||||
return ret;
|
||||
@ -97,7 +92,6 @@ static void thunderx_spi_remove(struct pci_dev *pdev)
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
clk_disable_unprepare(p->clk);
|
||||
pci_release_regions(pdev);
|
||||
/* Put everything in a known state. */
|
||||
writeq(0, p->register_base + OCTEON_SPI_CFG(p));
|
||||
|
@ -915,14 +915,11 @@ static int davinci_spi_probe(struct platform_device *pdev)
|
||||
|
||||
dspi->bitbang.master = host;
|
||||
|
||||
dspi->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
dspi->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(dspi->clk)) {
|
||||
ret = -ENODEV;
|
||||
goto free_host;
|
||||
}
|
||||
ret = clk_prepare_enable(dspi->clk);
|
||||
if (ret)
|
||||
goto free_host;
|
||||
|
||||
host->use_gpio_descriptors = true;
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
@ -947,7 +944,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
|
||||
|
||||
ret = davinci_spi_request_dma(dspi);
|
||||
if (ret == -EPROBE_DEFER) {
|
||||
goto free_clk;
|
||||
goto free_host;
|
||||
} else if (ret) {
|
||||
dev_info(&pdev->dev, "DMA is not supported (%d)\n", ret);
|
||||
dspi->dma_rx = NULL;
|
||||
@ -991,8 +988,6 @@ free_dma:
|
||||
dma_release_channel(dspi->dma_rx);
|
||||
dma_release_channel(dspi->dma_tx);
|
||||
}
|
||||
free_clk:
|
||||
clk_disable_unprepare(dspi->clk);
|
||||
free_host:
|
||||
spi_controller_put(host);
|
||||
err:
|
||||
@ -1018,8 +1013,6 @@ static void davinci_spi_remove(struct platform_device *pdev)
|
||||
|
||||
spi_bitbang_stop(&dspi->bitbang);
|
||||
|
||||
clk_disable_unprepare(dspi->clk);
|
||||
|
||||
if (dspi->dma_rx) {
|
||||
dma_release_channel(dspi->dma_rx);
|
||||
dma_release_channel(dspi->dma_tx);
|
||||
|
@ -269,43 +269,32 @@ static int dw_spi_bt1_probe(struct platform_device *pdev)
|
||||
|
||||
dws->paddr = mem->start;
|
||||
|
||||
dwsbt1->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
dwsbt1->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(dwsbt1->clk))
|
||||
return PTR_ERR(dwsbt1->clk);
|
||||
|
||||
ret = clk_prepare_enable(dwsbt1->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dws->bus_num = pdev->id;
|
||||
dws->reg_io_width = 4;
|
||||
dws->max_freq = clk_get_rate(dwsbt1->clk);
|
||||
if (!dws->max_freq) {
|
||||
ret = -EINVAL;
|
||||
goto err_disable_clk;
|
||||
}
|
||||
if (!dws->max_freq)
|
||||
return -EINVAL;
|
||||
|
||||
init_func = device_get_match_data(&pdev->dev);
|
||||
ret = init_func(pdev, dwsbt1);
|
||||
if (ret)
|
||||
goto err_disable_clk;
|
||||
return ret;
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
ret = dw_spi_add_host(&pdev->dev, dws);
|
||||
if (ret) {
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
goto err_disable_clk;
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, dwsbt1);
|
||||
|
||||
return 0;
|
||||
|
||||
err_disable_clk:
|
||||
clk_disable_unprepare(dwsbt1->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dw_spi_bt1_remove(struct platform_device *pdev)
|
||||
@ -315,8 +304,6 @@ static void dw_spi_bt1_remove(struct platform_device *pdev)
|
||||
dw_spi_remove_host(&dwsbt1->dws);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
clk_disable_unprepare(dwsbt1->clk);
|
||||
}
|
||||
|
||||
static const struct of_device_id dw_spi_bt1_of_match[] = {
|
||||
|
@ -340,29 +340,20 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
|
||||
if (dws->irq < 0)
|
||||
return dws->irq; /* -ENXIO */
|
||||
|
||||
dwsmmio->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
dwsmmio->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(dwsmmio->clk))
|
||||
return PTR_ERR(dwsmmio->clk);
|
||||
ret = clk_prepare_enable(dwsmmio->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Optional clock needed to access the registers */
|
||||
dwsmmio->pclk = devm_clk_get_optional(&pdev->dev, "pclk");
|
||||
if (IS_ERR(dwsmmio->pclk)) {
|
||||
ret = PTR_ERR(dwsmmio->pclk);
|
||||
goto out_clk;
|
||||
}
|
||||
ret = clk_prepare_enable(dwsmmio->pclk);
|
||||
if (ret)
|
||||
goto out_clk;
|
||||
dwsmmio->pclk = devm_clk_get_optional_enabled(&pdev->dev, "pclk");
|
||||
if (IS_ERR(dwsmmio->pclk))
|
||||
return PTR_ERR(dwsmmio->pclk);
|
||||
|
||||
/* find an optional reset controller */
|
||||
dwsmmio->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, "spi");
|
||||
if (IS_ERR(dwsmmio->rstc)) {
|
||||
ret = PTR_ERR(dwsmmio->rstc);
|
||||
goto out_clk;
|
||||
}
|
||||
if (IS_ERR(dwsmmio->rstc))
|
||||
return PTR_ERR(dwsmmio->rstc);
|
||||
|
||||
reset_control_deassert(dwsmmio->rstc);
|
||||
|
||||
dws->bus_num = pdev->id;
|
||||
@ -383,7 +374,7 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
|
||||
if (init_func) {
|
||||
ret = init_func(pdev, dwsmmio);
|
||||
if (ret)
|
||||
goto out;
|
||||
goto out_reset;
|
||||
}
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
@ -397,9 +388,7 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
|
||||
|
||||
out:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
clk_disable_unprepare(dwsmmio->pclk);
|
||||
out_clk:
|
||||
clk_disable_unprepare(dwsmmio->clk);
|
||||
out_reset:
|
||||
reset_control_assert(dwsmmio->rstc);
|
||||
|
||||
return ret;
|
||||
@ -411,8 +400,6 @@ static void dw_spi_mmio_remove(struct platform_device *pdev)
|
||||
|
||||
dw_spi_remove_host(&dwsmmio->dws);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
clk_disable_unprepare(dwsmmio->pclk);
|
||||
clk_disable_unprepare(dwsmmio->clk);
|
||||
reset_control_assert(dwsmmio->rstc);
|
||||
}
|
||||
|
||||
|
@ -1372,19 +1372,16 @@ static int dspi_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
dspi->clk = devm_clk_get(&pdev->dev, "dspi");
|
||||
dspi->clk = devm_clk_get_enabled(&pdev->dev, "dspi");
|
||||
if (IS_ERR(dspi->clk)) {
|
||||
ret = PTR_ERR(dspi->clk);
|
||||
dev_err(&pdev->dev, "unable to get clock\n");
|
||||
goto out_ctlr_put;
|
||||
}
|
||||
ret = clk_prepare_enable(dspi->clk);
|
||||
if (ret)
|
||||
goto out_ctlr_put;
|
||||
|
||||
ret = dspi_init(dspi);
|
||||
if (ret)
|
||||
goto out_clk_put;
|
||||
goto out_ctlr_put;
|
||||
|
||||
dspi->irq = platform_get_irq(pdev, 0);
|
||||
if (dspi->irq <= 0) {
|
||||
@ -1400,7 +1397,7 @@ static int dspi_probe(struct platform_device *pdev)
|
||||
IRQF_SHARED, pdev->name, dspi);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Unable to attach DSPI interrupt\n");
|
||||
goto out_clk_put;
|
||||
goto out_ctlr_put;
|
||||
}
|
||||
|
||||
poll_mode:
|
||||
@ -1432,8 +1429,6 @@ out_release_dma:
|
||||
out_free_irq:
|
||||
if (dspi->irq)
|
||||
free_irq(dspi->irq, dspi);
|
||||
out_clk_put:
|
||||
clk_disable_unprepare(dspi->clk);
|
||||
out_ctlr_put:
|
||||
spi_controller_put(ctlr);
|
||||
|
||||
@ -1458,7 +1453,6 @@ static void dspi_remove(struct platform_device *pdev)
|
||||
dspi_release_dma(dspi);
|
||||
if (dspi->irq)
|
||||
free_irq(dspi->irq, dspi);
|
||||
clk_disable_unprepare(dspi->clk);
|
||||
}
|
||||
|
||||
static void dspi_shutdown(struct platform_device *pdev)
|
||||
|
@ -166,7 +166,7 @@ static void handle_se_timeout(struct spi_master *spi,
|
||||
* doesn`t support CMD Cancel sequnece
|
||||
*/
|
||||
spin_unlock_irq(&mas->lock);
|
||||
goto unmap_if_dma;
|
||||
goto reset_if_dma;
|
||||
}
|
||||
|
||||
reinit_completion(&mas->cancel_done);
|
||||
@ -175,7 +175,7 @@ static void handle_se_timeout(struct spi_master *spi,
|
||||
|
||||
time_left = wait_for_completion_timeout(&mas->cancel_done, HZ);
|
||||
if (time_left)
|
||||
goto unmap_if_dma;
|
||||
goto reset_if_dma;
|
||||
|
||||
spin_lock_irq(&mas->lock);
|
||||
reinit_completion(&mas->abort_done);
|
||||
@ -193,7 +193,7 @@ static void handle_se_timeout(struct spi_master *spi,
|
||||
mas->abort_failed = true;
|
||||
}
|
||||
|
||||
unmap_if_dma:
|
||||
reset_if_dma:
|
||||
if (mas->cur_xfer_mode == GENI_SE_DMA) {
|
||||
if (xfer) {
|
||||
if (xfer->tx_buf) {
|
||||
|
@ -932,14 +932,11 @@ static int lantiq_ssc_probe(struct platform_device *pdev)
|
||||
if (err)
|
||||
goto err_host_put;
|
||||
|
||||
spi->spi_clk = devm_clk_get(dev, "gate");
|
||||
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;
|
||||
}
|
||||
err = clk_prepare_enable(spi->spi_clk);
|
||||
if (err)
|
||||
goto err_host_put;
|
||||
|
||||
/*
|
||||
* Use the old clk_get_fpi() function on Lantiq platform, till it
|
||||
@ -952,7 +949,7 @@ static int lantiq_ssc_probe(struct platform_device *pdev)
|
||||
#endif
|
||||
if (IS_ERR(spi->fpi_clk)) {
|
||||
err = PTR_ERR(spi->fpi_clk);
|
||||
goto err_clk_disable;
|
||||
goto err_host_put;
|
||||
}
|
||||
|
||||
num_cs = 8;
|
||||
@ -1010,8 +1007,6 @@ err_wq_destroy:
|
||||
destroy_workqueue(spi->wq);
|
||||
err_clk_put:
|
||||
clk_put(spi->fpi_clk);
|
||||
err_clk_disable:
|
||||
clk_disable_unprepare(spi->spi_clk);
|
||||
err_host_put:
|
||||
spi_controller_put(host);
|
||||
|
||||
@ -1029,7 +1024,6 @@ static void lantiq_ssc_remove(struct platform_device *pdev)
|
||||
hw_enter_config_mode(spi);
|
||||
|
||||
destroy_workqueue(spi->wq);
|
||||
clk_disable_unprepare(spi->spi_clk);
|
||||
clk_put(spi->fpi_clk);
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
* the SPI/Microwire bus interface. This driver specifically supports an
|
||||
* NS LM70 LLP Evaluation Board, interfacing to a PC using its parallel
|
||||
* port to bitbang an SPI-parport bridge. Accordingly, this is an SPI
|
||||
* master controller driver. The hwmon/lm70 driver is a "SPI protocol
|
||||
* host controller driver. The hwmon/lm70 driver is a "SPI protocol
|
||||
* driver", layered on top of this one and usable without the lm70llp.
|
||||
*
|
||||
* Datasheet and Schematic:
|
||||
@ -189,7 +189,7 @@ static void spi_lm70llp_attach(struct parport *p)
|
||||
{
|
||||
struct pardevice *pd;
|
||||
struct spi_lm70llp *pp;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
int status;
|
||||
struct pardev_cb lm70llp_cb;
|
||||
|
||||
@ -202,17 +202,17 @@ static void spi_lm70llp_attach(struct parport *p)
|
||||
* the lm70 driver could verify it, reading the manf ID.
|
||||
*/
|
||||
|
||||
master = spi_alloc_master(p->physport->dev, sizeof(*pp));
|
||||
if (!master) {
|
||||
host = spi_alloc_host(p->physport->dev, sizeof(*pp));
|
||||
if (!host) {
|
||||
status = -ENOMEM;
|
||||
goto out_fail;
|
||||
}
|
||||
pp = spi_master_get_devdata(master);
|
||||
pp = spi_controller_get_devdata(host);
|
||||
|
||||
/*
|
||||
* SPI and bitbang hookup.
|
||||
*/
|
||||
pp->bitbang.master = master;
|
||||
pp->bitbang.master = host;
|
||||
pp->bitbang.chipselect = lm70_chipselect;
|
||||
pp->bitbang.txrx_word[SPI_MODE_0] = lm70_txrx;
|
||||
pp->bitbang.flags = SPI_3WIRE;
|
||||
@ -228,7 +228,7 @@ static void spi_lm70llp_attach(struct parport *p)
|
||||
|
||||
if (!pd) {
|
||||
status = -ENOMEM;
|
||||
goto out_free_master;
|
||||
goto out_free_host;
|
||||
}
|
||||
pp->pd = pd;
|
||||
|
||||
@ -287,8 +287,8 @@ out_off_and_release:
|
||||
parport_release(pp->pd);
|
||||
out_parport_unreg:
|
||||
parport_unregister_device(pd);
|
||||
out_free_master:
|
||||
spi_master_put(master);
|
||||
out_free_host:
|
||||
spi_controller_put(host);
|
||||
out_fail:
|
||||
pr_info("spi_lm70llp probe fail, status %d\n", status);
|
||||
}
|
||||
@ -309,7 +309,7 @@ static void spi_lm70llp_detach(struct parport *p)
|
||||
parport_release(pp->pd);
|
||||
parport_unregister_device(pp->pd);
|
||||
|
||||
spi_master_put(pp->bitbang.master);
|
||||
spi_controller_put(pp->bitbang.master);
|
||||
|
||||
lm70llp = NULL;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* SPI master driver for ICP DAS LP-8841 RTC
|
||||
* SPI host driver for ICP DAS LP-8841 RTC
|
||||
*
|
||||
* Copyright (C) 2016 Sergei Ianovich
|
||||
*
|
||||
@ -73,13 +73,13 @@ bitbang_txrx_be_cpha0_lsb(struct spi_lp8841_rtc *data,
|
||||
/* clock starts at inactive polarity */
|
||||
for (; likely(bits); bits--) {
|
||||
|
||||
/* setup LSB (to slave) on leading edge */
|
||||
/* setup LSB (to target) on leading edge */
|
||||
if ((flags & SPI_CONTROLLER_NO_TX) == 0)
|
||||
setmosi(data, (word & 1));
|
||||
|
||||
usleep_range(usecs, usecs + 1); /* T(setup) */
|
||||
|
||||
/* sample LSB (from slave) on trailing edge */
|
||||
/* sample LSB (from target) on trailing edge */
|
||||
word >>= 1;
|
||||
if ((flags & SPI_CONTROLLER_NO_RX) == 0)
|
||||
word |= (getmiso(data) << 31);
|
||||
@ -95,11 +95,11 @@ bitbang_txrx_be_cpha0_lsb(struct spi_lp8841_rtc *data,
|
||||
}
|
||||
|
||||
static int
|
||||
spi_lp8841_rtc_transfer_one(struct spi_master *master,
|
||||
spi_lp8841_rtc_transfer_one(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *t)
|
||||
{
|
||||
struct spi_lp8841_rtc *data = spi_master_get_devdata(master);
|
||||
struct spi_lp8841_rtc *data = spi_controller_get_devdata(host);
|
||||
unsigned count = t->len;
|
||||
const u8 *tx = t->tx_buf;
|
||||
u8 *rx = t->rx_buf;
|
||||
@ -128,7 +128,7 @@ spi_lp8841_rtc_transfer_one(struct spi_master *master,
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
spi_finalize_current_transfer(master);
|
||||
spi_finalize_current_transfer(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -136,7 +136,7 @@ spi_lp8841_rtc_transfer_one(struct spi_master *master,
|
||||
static void
|
||||
spi_lp8841_rtc_set_cs(struct spi_device *spi, bool enable)
|
||||
{
|
||||
struct spi_lp8841_rtc *data = spi_master_get_devdata(spi->master);
|
||||
struct spi_lp8841_rtc *data = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
data->state = 0;
|
||||
writeb(data->state, data->iomem);
|
||||
@ -182,48 +182,48 @@ static int
|
||||
spi_lp8841_rtc_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct spi_lp8841_rtc *data;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(*data));
|
||||
if (!master)
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*data));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
platform_set_drvdata(pdev, master);
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
||||
master->flags = SPI_CONTROLLER_HALF_DUPLEX;
|
||||
master->mode_bits = SPI_CS_HIGH | SPI_3WIRE | SPI_LSB_FIRST;
|
||||
host->flags = SPI_CONTROLLER_HALF_DUPLEX;
|
||||
host->mode_bits = SPI_CS_HIGH | SPI_3WIRE | SPI_LSB_FIRST;
|
||||
|
||||
master->bus_num = pdev->id;
|
||||
master->num_chipselect = 1;
|
||||
master->setup = spi_lp8841_rtc_setup;
|
||||
master->set_cs = spi_lp8841_rtc_set_cs;
|
||||
master->transfer_one = spi_lp8841_rtc_transfer_one;
|
||||
master->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
host->bus_num = pdev->id;
|
||||
host->num_chipselect = 1;
|
||||
host->setup = spi_lp8841_rtc_setup;
|
||||
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
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
#endif
|
||||
|
||||
data = spi_master_get_devdata(master);
|
||||
data = spi_controller_get_devdata(host);
|
||||
|
||||
data->iomem = devm_platform_ioremap_resource(pdev, 0);
|
||||
ret = PTR_ERR_OR_ZERO(data->iomem);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to get IO address\n");
|
||||
goto err_put_master;
|
||||
goto err_put_host;
|
||||
}
|
||||
|
||||
/* register with the SPI framework */
|
||||
ret = devm_spi_register_master(&pdev->dev, master);
|
||||
ret = devm_spi_register_controller(&pdev->dev, host);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "cannot register spi master\n");
|
||||
goto err_put_master;
|
||||
dev_err(&pdev->dev, "cannot register spi host\n");
|
||||
goto err_put_host;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
|
||||
err_put_master:
|
||||
spi_master_put(master);
|
||||
err_put_host:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -239,6 +239,6 @@ static struct platform_driver spi_lp8841_rtc_driver = {
|
||||
};
|
||||
module_platform_driver(spi_lp8841_rtc_driver);
|
||||
|
||||
MODULE_DESCRIPTION("SPI master driver for ICP DAS LP-8841 RTC");
|
||||
MODULE_DESCRIPTION("SPI host driver for ICP DAS LP-8841 RTC");
|
||||
MODULE_AUTHOR("Sergei Ianovich");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -151,7 +151,7 @@ struct meson_spicc_data {
|
||||
};
|
||||
|
||||
struct meson_spicc_device {
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct platform_device *pdev;
|
||||
void __iomem *base;
|
||||
struct clk *core;
|
||||
@ -399,11 +399,11 @@ static void meson_spicc_reset_fifo(struct meson_spicc_device *spicc)
|
||||
spicc->base + SPICC_ENH_CTL0);
|
||||
}
|
||||
|
||||
static int meson_spicc_transfer_one(struct spi_master *master,
|
||||
static int meson_spicc_transfer_one(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
struct meson_spicc_device *spicc = spi_master_get_devdata(master);
|
||||
struct meson_spicc_device *spicc = spi_controller_get_devdata(host);
|
||||
uint64_t timeout;
|
||||
|
||||
/* Store current transfer */
|
||||
@ -454,10 +454,10 @@ static int meson_spicc_transfer_one(struct spi_master *master,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int meson_spicc_prepare_message(struct spi_master *master,
|
||||
static int meson_spicc_prepare_message(struct spi_controller *host,
|
||||
struct spi_message *message)
|
||||
{
|
||||
struct meson_spicc_device *spicc = spi_master_get_devdata(master);
|
||||
struct meson_spicc_device *spicc = spi_controller_get_devdata(host);
|
||||
struct spi_device *spi = message->spi;
|
||||
u32 conf = readl_relaxed(spicc->base + SPICC_CONREG) & SPICC_DATARATE_MASK;
|
||||
|
||||
@ -519,9 +519,9 @@ static int meson_spicc_prepare_message(struct spi_master *master,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int meson_spicc_unprepare_transfer(struct spi_master *master)
|
||||
static int meson_spicc_unprepare_transfer(struct spi_controller *host)
|
||||
{
|
||||
struct meson_spicc_device *spicc = spi_master_get_devdata(master);
|
||||
struct meson_spicc_device *spicc = spi_controller_get_devdata(host);
|
||||
u32 conf = readl_relaxed(spicc->base + SPICC_CONREG) & SPICC_DATARATE_MASK;
|
||||
|
||||
/* Disable all IRQs */
|
||||
@ -541,7 +541,7 @@ static int meson_spicc_unprepare_transfer(struct spi_master *master)
|
||||
static int meson_spicc_setup(struct spi_device *spi)
|
||||
{
|
||||
if (!spi->controller_state)
|
||||
spi->controller_state = spi_master_get_devdata(spi->master);
|
||||
spi->controller_state = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -585,7 +585,7 @@ static unsigned long meson_spicc_pow2_recalc_rate(struct clk_hw *hw,
|
||||
struct clk_divider *divider = to_clk_divider(hw);
|
||||
struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider);
|
||||
|
||||
if (!spicc->master->cur_msg)
|
||||
if (!spicc->host->cur_msg)
|
||||
return 0;
|
||||
|
||||
return clk_divider_ops.recalc_rate(hw, parent_rate);
|
||||
@ -597,7 +597,7 @@ static int meson_spicc_pow2_determine_rate(struct clk_hw *hw,
|
||||
struct clk_divider *divider = to_clk_divider(hw);
|
||||
struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider);
|
||||
|
||||
if (!spicc->master->cur_msg)
|
||||
if (!spicc->host->cur_msg)
|
||||
return -EINVAL;
|
||||
|
||||
return clk_divider_ops.determine_rate(hw, req);
|
||||
@ -609,7 +609,7 @@ static int meson_spicc_pow2_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
struct clk_divider *divider = to_clk_divider(hw);
|
||||
struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider);
|
||||
|
||||
if (!spicc->master->cur_msg)
|
||||
if (!spicc->host->cur_msg)
|
||||
return -EINVAL;
|
||||
|
||||
return clk_divider_ops.set_rate(hw, rate, parent_rate);
|
||||
@ -769,23 +769,23 @@ static int meson_spicc_enh_clk_init(struct meson_spicc_device *spicc)
|
||||
|
||||
static int meson_spicc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct meson_spicc_device *spicc;
|
||||
int ret, irq;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(*spicc));
|
||||
if (!master) {
|
||||
dev_err(&pdev->dev, "master allocation failed\n");
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*spicc));
|
||||
if (!host) {
|
||||
dev_err(&pdev->dev, "host allocation failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
spicc = spi_master_get_devdata(master);
|
||||
spicc->master = master;
|
||||
spicc = spi_controller_get_devdata(host);
|
||||
spicc->host = host;
|
||||
|
||||
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_master;
|
||||
goto out_host;
|
||||
}
|
||||
|
||||
spicc->pdev = pdev;
|
||||
@ -797,7 +797,7 @@ static int meson_spicc_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(spicc->base)) {
|
||||
dev_err(&pdev->dev, "io resource mapping failed\n");
|
||||
ret = PTR_ERR(spicc->base);
|
||||
goto out_master;
|
||||
goto out_host;
|
||||
}
|
||||
|
||||
/* Set master mode and enable controller */
|
||||
@ -810,101 +810,83 @@ static int meson_spicc_probe(struct platform_device *pdev)
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
ret = irq;
|
||||
goto out_master;
|
||||
goto out_host;
|
||||
}
|
||||
|
||||
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_master;
|
||||
goto out_host;
|
||||
}
|
||||
|
||||
spicc->core = devm_clk_get(&pdev->dev, "core");
|
||||
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_master;
|
||||
goto out_host;
|
||||
}
|
||||
|
||||
if (spicc->data->has_pclk) {
|
||||
spicc->pclk = devm_clk_get(&pdev->dev, "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_master;
|
||||
goto out_host;
|
||||
}
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(spicc->core);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "core clock enable failed\n");
|
||||
goto out_master;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(spicc->pclk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "pclk clock enable failed\n");
|
||||
goto out_core_clk;
|
||||
}
|
||||
|
||||
spicc->pinctrl = devm_pinctrl_get(&pdev->dev);
|
||||
if (IS_ERR(spicc->pinctrl)) {
|
||||
ret = PTR_ERR(spicc->pinctrl);
|
||||
goto out_clk;
|
||||
goto out_host;
|
||||
}
|
||||
|
||||
device_reset_optional(&pdev->dev);
|
||||
|
||||
master->num_chipselect = 4;
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH;
|
||||
master->bits_per_word_mask = SPI_BPW_MASK(32) |
|
||||
SPI_BPW_MASK(24) |
|
||||
SPI_BPW_MASK(16) |
|
||||
SPI_BPW_MASK(8);
|
||||
master->flags = (SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX);
|
||||
master->min_speed_hz = spicc->data->min_speed_hz;
|
||||
master->max_speed_hz = spicc->data->max_speed_hz;
|
||||
master->setup = meson_spicc_setup;
|
||||
master->cleanup = meson_spicc_cleanup;
|
||||
master->prepare_message = meson_spicc_prepare_message;
|
||||
master->unprepare_transfer_hardware = meson_spicc_unprepare_transfer;
|
||||
master->transfer_one = meson_spicc_transfer_one;
|
||||
master->use_gpio_descriptors = true;
|
||||
host->num_chipselect = 4;
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
host->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH;
|
||||
host->bits_per_word_mask = SPI_BPW_MASK(32) |
|
||||
SPI_BPW_MASK(24) |
|
||||
SPI_BPW_MASK(16) |
|
||||
SPI_BPW_MASK(8);
|
||||
host->flags = (SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX);
|
||||
host->min_speed_hz = spicc->data->min_speed_hz;
|
||||
host->max_speed_hz = spicc->data->max_speed_hz;
|
||||
host->setup = meson_spicc_setup;
|
||||
host->cleanup = meson_spicc_cleanup;
|
||||
host->prepare_message = meson_spicc_prepare_message;
|
||||
host->unprepare_transfer_hardware = meson_spicc_unprepare_transfer;
|
||||
host->transfer_one = meson_spicc_transfer_one;
|
||||
host->use_gpio_descriptors = true;
|
||||
|
||||
meson_spicc_oen_enable(spicc);
|
||||
|
||||
ret = meson_spicc_pow2_clk_init(spicc);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "pow2 clock registration failed\n");
|
||||
goto out_clk;
|
||||
goto out_host;
|
||||
}
|
||||
|
||||
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_clk;
|
||||
goto out_host;
|
||||
}
|
||||
}
|
||||
|
||||
ret = devm_spi_register_master(&pdev->dev, master);
|
||||
ret = devm_spi_register_controller(&pdev->dev, host);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "spi master registration failed\n");
|
||||
goto out_clk;
|
||||
dev_err(&pdev->dev, "spi registration failed\n");
|
||||
goto out_host;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_clk:
|
||||
clk_disable_unprepare(spicc->pclk);
|
||||
|
||||
out_core_clk:
|
||||
clk_disable_unprepare(spicc->core);
|
||||
|
||||
out_master:
|
||||
spi_master_put(master);
|
||||
out_host:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -916,10 +898,7 @@ static void meson_spicc_remove(struct platform_device *pdev)
|
||||
/* Disable SPI */
|
||||
writel(0, spicc->base + SPICC_CONREG);
|
||||
|
||||
clk_disable_unprepare(spicc->core);
|
||||
clk_disable_unprepare(spicc->pclk);
|
||||
|
||||
spi_master_put(spicc->master);
|
||||
spi_controller_put(spicc->host);
|
||||
}
|
||||
|
||||
static const struct meson_spicc_data meson_spicc_gx_data = {
|
||||
|
@ -67,13 +67,13 @@
|
||||
|
||||
/**
|
||||
* struct meson_spifc
|
||||
* @master: the SPI master
|
||||
* @host: the SPI host
|
||||
* @regmap: regmap for device registers
|
||||
* @clk: input clock of the built-in baud rate generator
|
||||
* @dev: the device structure
|
||||
*/
|
||||
struct meson_spifc {
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct regmap *regmap;
|
||||
struct clk *clk;
|
||||
struct device *dev;
|
||||
@ -237,16 +237,16 @@ static int meson_spifc_txrx(struct meson_spifc *spifc,
|
||||
|
||||
/**
|
||||
* meson_spifc_transfer_one() - perform a single transfer
|
||||
* @master: the SPI master
|
||||
* @host: the SPI host
|
||||
* @spi: the SPI device
|
||||
* @xfer: the current SPI transfer
|
||||
* Return: 0 on success, a negative value on error
|
||||
*/
|
||||
static int meson_spifc_transfer_one(struct spi_master *master,
|
||||
static int meson_spifc_transfer_one(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
struct meson_spifc *spifc = spi_master_get_devdata(master);
|
||||
struct meson_spifc *spifc = spi_controller_get_devdata(host);
|
||||
int len, done = 0, ret = 0;
|
||||
|
||||
meson_spifc_setup_speed(spifc, xfer->speed_hz);
|
||||
@ -256,7 +256,7 @@ static int meson_spifc_transfer_one(struct spi_master *master,
|
||||
while (done < xfer->len && !ret) {
|
||||
len = min_t(int, xfer->len - done, SPIFC_BUFFER_SIZE);
|
||||
ret = meson_spifc_txrx(spifc, xfer, done, len,
|
||||
spi_transfer_is_last(master, xfer),
|
||||
spi_transfer_is_last(host, xfer),
|
||||
done + len >= xfer->len);
|
||||
done += len;
|
||||
}
|
||||
@ -284,19 +284,19 @@ static void meson_spifc_hw_init(struct meson_spifc *spifc)
|
||||
|
||||
static int meson_spifc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct meson_spifc *spifc;
|
||||
void __iomem *base;
|
||||
unsigned int rate;
|
||||
int ret = 0;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(struct meson_spifc));
|
||||
if (!master)
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(struct meson_spifc));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
||||
spifc = spi_master_get_devdata(master);
|
||||
spifc = spi_controller_get_devdata(host);
|
||||
spifc->dev = &pdev->dev;
|
||||
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
@ -312,67 +312,56 @@ static int meson_spifc_probe(struct platform_device *pdev)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
spifc->clk = devm_clk_get(spifc->dev, NULL);
|
||||
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;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(spifc->clk);
|
||||
if (ret) {
|
||||
dev_err(spifc->dev, "can't prepare clock\n");
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
rate = clk_get_rate(spifc->clk);
|
||||
|
||||
master->num_chipselect = 1;
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
master->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
master->auto_runtime_pm = true;
|
||||
master->transfer_one = meson_spifc_transfer_one;
|
||||
master->min_speed_hz = rate >> 6;
|
||||
master->max_speed_hz = rate >> 1;
|
||||
host->num_chipselect = 1;
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
host->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
host->auto_runtime_pm = true;
|
||||
host->transfer_one = meson_spifc_transfer_one;
|
||||
host->min_speed_hz = rate >> 6;
|
||||
host->max_speed_hz = rate >> 1;
|
||||
|
||||
meson_spifc_hw_init(spifc);
|
||||
|
||||
pm_runtime_set_active(spifc->dev);
|
||||
pm_runtime_enable(spifc->dev);
|
||||
|
||||
ret = devm_spi_register_master(spifc->dev, master);
|
||||
ret = devm_spi_register_controller(spifc->dev, host);
|
||||
if (ret) {
|
||||
dev_err(spifc->dev, "failed to register spi master\n");
|
||||
goto out_clk;
|
||||
dev_err(spifc->dev, "failed to register spi host\n");
|
||||
goto out_pm;
|
||||
}
|
||||
|
||||
return 0;
|
||||
out_clk:
|
||||
clk_disable_unprepare(spifc->clk);
|
||||
out_pm:
|
||||
pm_runtime_disable(spifc->dev);
|
||||
out_err:
|
||||
spi_master_put(master);
|
||||
spi_controller_put(host);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void meson_spifc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master = platform_get_drvdata(pdev);
|
||||
struct meson_spifc *spifc = spi_master_get_devdata(master);
|
||||
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
clk_disable_unprepare(spifc->clk);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int meson_spifc_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct meson_spifc *spifc = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct meson_spifc *spifc = spi_controller_get_devdata(host);
|
||||
int ret;
|
||||
|
||||
ret = spi_master_suspend(master);
|
||||
ret = spi_controller_suspend(host);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -384,8 +373,8 @@ static int meson_spifc_suspend(struct device *dev)
|
||||
|
||||
static int meson_spifc_resume(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct meson_spifc *spifc = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct meson_spifc *spifc = spi_controller_get_devdata(host);
|
||||
int ret;
|
||||
|
||||
if (!pm_runtime_suspended(dev)) {
|
||||
@ -396,7 +385,7 @@ static int meson_spifc_resume(struct device *dev)
|
||||
|
||||
meson_spifc_hw_init(spifc);
|
||||
|
||||
ret = spi_master_resume(master);
|
||||
ret = spi_controller_resume(host);
|
||||
if (ret)
|
||||
clk_disable_unprepare(spifc->clk);
|
||||
|
||||
@ -407,8 +396,8 @@ static int meson_spifc_resume(struct device *dev)
|
||||
#ifdef CONFIG_PM
|
||||
static int meson_spifc_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct meson_spifc *spifc = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct meson_spifc *spifc = spi_controller_get_devdata(host);
|
||||
|
||||
clk_disable_unprepare(spifc->clk);
|
||||
|
||||
@ -417,8 +406,8 @@ static int meson_spifc_runtime_suspend(struct device *dev)
|
||||
|
||||
static int meson_spifc_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct meson_spifc *spifc = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct meson_spifc *spifc = spi_controller_get_devdata(host);
|
||||
|
||||
return clk_prepare_enable(spifc->clk);
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ static int mchp_coreqspi_setup_clock(struct mchp_coreqspi *qspi, struct spi_devi
|
||||
|
||||
static int mchp_coreqspi_setup_op(struct spi_device *spi_dev)
|
||||
{
|
||||
struct spi_controller *ctlr = spi_dev->master;
|
||||
struct spi_controller *ctlr = spi_dev->controller;
|
||||
struct mchp_coreqspi *qspi = spi_controller_get_devdata(ctlr);
|
||||
u32 control = readl_relaxed(qspi->regs + REG_CONTROL);
|
||||
|
||||
@ -368,7 +368,7 @@ static inline void mchp_coreqspi_config_op(struct mchp_coreqspi *qspi, const str
|
||||
static int mchp_qspi_wait_for_ready(struct spi_mem *mem)
|
||||
{
|
||||
struct mchp_coreqspi *qspi = spi_controller_get_devdata
|
||||
(mem->spi->master);
|
||||
(mem->spi->controller);
|
||||
u32 status;
|
||||
int ret;
|
||||
|
||||
@ -387,7 +387,7 @@ static int mchp_qspi_wait_for_ready(struct spi_mem *mem)
|
||||
static int mchp_coreqspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||
{
|
||||
struct mchp_coreqspi *qspi = spi_controller_get_devdata
|
||||
(mem->spi->master);
|
||||
(mem->spi->controller);
|
||||
u32 address = op->addr.val;
|
||||
u8 opcode = op->cmd.opcode;
|
||||
u8 opaddr[5];
|
||||
@ -505,10 +505,10 @@ static int mchp_coreqspi_probe(struct platform_device *pdev)
|
||||
struct device_node *np = dev->of_node;
|
||||
int ret;
|
||||
|
||||
ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(*qspi));
|
||||
ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*qspi));
|
||||
if (!ctlr)
|
||||
return dev_err_probe(&pdev->dev, -ENOMEM,
|
||||
"unable to allocate master for QSPI controller\n");
|
||||
"unable to allocate host for QSPI controller\n");
|
||||
|
||||
qspi = spi_controller_get_devdata(ctlr);
|
||||
platform_set_drvdata(pdev, qspi);
|
||||
@ -518,30 +518,23 @@ static int mchp_coreqspi_probe(struct platform_device *pdev)
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(qspi->regs),
|
||||
"failed to map registers\n");
|
||||
|
||||
qspi->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
qspi->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(qspi->clk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(qspi->clk),
|
||||
"could not get clock\n");
|
||||
|
||||
ret = clk_prepare_enable(qspi->clk);
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret,
|
||||
"failed to enable clock\n");
|
||||
|
||||
init_completion(&qspi->data_completion);
|
||||
mutex_init(&qspi->op_lock);
|
||||
|
||||
qspi->irq = platform_get_irq(pdev, 0);
|
||||
if (qspi->irq < 0) {
|
||||
ret = qspi->irq;
|
||||
goto out;
|
||||
}
|
||||
if (qspi->irq < 0)
|
||||
return qspi->irq;
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, qspi->irq, mchp_coreqspi_isr,
|
||||
IRQF_SHARED, pdev->name, qspi);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "request_irq failed %d\n", ret);
|
||||
goto out;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
@ -552,18 +545,11 @@ static int mchp_coreqspi_probe(struct platform_device *pdev)
|
||||
ctlr->dev.of_node = np;
|
||||
|
||||
ret = devm_spi_register_controller(&pdev->dev, ctlr);
|
||||
if (ret) {
|
||||
dev_err_probe(&pdev->dev, ret,
|
||||
"spi_register_controller failed\n");
|
||||
goto out;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret,
|
||||
"spi_register_controller failed\n");
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
clk_disable_unprepare(qspi->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mchp_coreqspi_remove(struct platform_device *pdev)
|
||||
@ -574,7 +560,6 @@ static void mchp_coreqspi_remove(struct platform_device *pdev)
|
||||
mchp_coreqspi_disable_ints(qspi);
|
||||
control &= ~CONTROL_ENABLE;
|
||||
writel_relaxed(control, qspi->regs + REG_CONTROL);
|
||||
clk_disable_unprepare(qspi->clk);
|
||||
}
|
||||
|
||||
static const struct of_device_id mchp_coreqspi_of_match[] = {
|
||||
|
@ -244,7 +244,7 @@ static inline void mchp_corespi_set_framesize(struct mchp_corespi *spi, int bt)
|
||||
static void mchp_corespi_set_cs(struct spi_device *spi, bool disable)
|
||||
{
|
||||
u32 reg;
|
||||
struct mchp_corespi *corespi = spi_master_get_devdata(spi->master);
|
||||
struct mchp_corespi *corespi = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
reg = mchp_corespi_read(corespi, REG_SLAVE_SELECT);
|
||||
reg &= ~BIT(spi_get_chipselect(spi, 0));
|
||||
@ -255,11 +255,11 @@ static void mchp_corespi_set_cs(struct spi_device *spi, bool disable)
|
||||
|
||||
static int mchp_corespi_setup(struct spi_device *spi)
|
||||
{
|
||||
struct mchp_corespi *corespi = spi_master_get_devdata(spi->master);
|
||||
struct mchp_corespi *corespi = spi_controller_get_devdata(spi->controller);
|
||||
u32 reg;
|
||||
|
||||
/*
|
||||
* Active high slaves need to be specifically set to their inactive
|
||||
* Active high targets need to be specifically set to their inactive
|
||||
* states during probe by adding them to the "control group" & thus
|
||||
* driving their select line low.
|
||||
*/
|
||||
@ -271,7 +271,7 @@ static int mchp_corespi_setup(struct spi_device *spi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mchp_corespi_init(struct spi_master *master, struct mchp_corespi *spi)
|
||||
static void mchp_corespi_init(struct spi_controller *host, struct mchp_corespi *spi)
|
||||
{
|
||||
unsigned long clk_hz;
|
||||
u32 control = mchp_corespi_read(spi, REG_CONTROL);
|
||||
@ -285,7 +285,7 @@ static void mchp_corespi_init(struct spi_master *master, struct mchp_corespi *sp
|
||||
|
||||
/* max. possible spi clock rate is the apb clock rate */
|
||||
clk_hz = clk_get_rate(spi->clk);
|
||||
master->max_speed_hz = clk_hz;
|
||||
host->max_speed_hz = clk_hz;
|
||||
|
||||
/*
|
||||
* The controller must be configured so that it doesn't remove Chip
|
||||
@ -305,7 +305,7 @@ static void mchp_corespi_init(struct spi_master *master, struct mchp_corespi *sp
|
||||
/*
|
||||
* It is required to enable direct mode, otherwise control over the chip
|
||||
* select is relinquished to the hardware. SSELOUT is enabled too so we
|
||||
* can deal with active high slaves.
|
||||
* can deal with active high targets.
|
||||
*/
|
||||
mchp_corespi_write(spi, REG_SLAVE_SELECT, SSELOUT | SSEL_DIRECT);
|
||||
|
||||
@ -371,8 +371,8 @@ static inline void mchp_corespi_set_mode(struct mchp_corespi *spi, unsigned int
|
||||
|
||||
static irqreturn_t mchp_corespi_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct spi_master *master = dev_id;
|
||||
struct mchp_corespi *spi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_id;
|
||||
struct mchp_corespi *spi = spi_controller_get_devdata(host);
|
||||
u32 intfield = mchp_corespi_read(spi, REG_MIS) & 0xf;
|
||||
bool finalise = false;
|
||||
|
||||
@ -399,7 +399,7 @@ static irqreturn_t mchp_corespi_interrupt(int irq, void *dev_id)
|
||||
if (intfield & INT_RX_CHANNEL_OVERFLOW) {
|
||||
mchp_corespi_write(spi, REG_INT_CLEAR, INT_RX_CHANNEL_OVERFLOW);
|
||||
finalise = true;
|
||||
dev_err(&master->dev,
|
||||
dev_err(&host->dev,
|
||||
"%s: RX OVERFLOW: rxlen: %d, txlen: %d\n", __func__,
|
||||
spi->rx_len, spi->tx_len);
|
||||
}
|
||||
@ -407,13 +407,13 @@ static irqreturn_t mchp_corespi_interrupt(int irq, void *dev_id)
|
||||
if (intfield & INT_TX_CHANNEL_UNDERRUN) {
|
||||
mchp_corespi_write(spi, REG_INT_CLEAR, INT_TX_CHANNEL_UNDERRUN);
|
||||
finalise = true;
|
||||
dev_err(&master->dev,
|
||||
dev_err(&host->dev,
|
||||
"%s: TX UNDERFLOW: rxlen: %d, txlen: %d\n", __func__,
|
||||
spi->rx_len, spi->tx_len);
|
||||
}
|
||||
|
||||
if (finalise)
|
||||
spi_finalize_current_transfer(master);
|
||||
spi_finalize_current_transfer(host);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -455,16 +455,16 @@ static int mchp_corespi_calculate_clkgen(struct mchp_corespi *spi,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mchp_corespi_transfer_one(struct spi_master *master,
|
||||
static int mchp_corespi_transfer_one(struct spi_controller *host,
|
||||
struct spi_device *spi_dev,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
struct mchp_corespi *spi = spi_master_get_devdata(master);
|
||||
struct mchp_corespi *spi = spi_controller_get_devdata(host);
|
||||
int ret;
|
||||
|
||||
ret = mchp_corespi_calculate_clkgen(spi, (unsigned long)xfer->speed_hz);
|
||||
if (ret) {
|
||||
dev_err(&master->dev, "failed to set clk_gen for target %u Hz\n", xfer->speed_hz);
|
||||
dev_err(&host->dev, "failed to set clk_gen for target %u Hz\n", xfer->speed_hz);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -484,11 +484,11 @@ static int mchp_corespi_transfer_one(struct spi_master *master,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mchp_corespi_prepare_message(struct spi_master *master,
|
||||
static int mchp_corespi_prepare_message(struct spi_controller *host,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
struct spi_device *spi_dev = msg->spi;
|
||||
struct mchp_corespi *spi = spi_master_get_devdata(master);
|
||||
struct mchp_corespi *spi = spi_controller_get_devdata(host);
|
||||
|
||||
mchp_corespi_set_framesize(spi, DEFAULT_FRAMESIZE);
|
||||
mchp_corespi_set_mode(spi, spi_dev->mode);
|
||||
@ -498,32 +498,32 @@ static int mchp_corespi_prepare_message(struct spi_master *master,
|
||||
|
||||
static int mchp_corespi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct mchp_corespi *spi;
|
||||
struct resource *res;
|
||||
u32 num_cs;
|
||||
int ret = 0;
|
||||
|
||||
master = devm_spi_alloc_master(&pdev->dev, sizeof(*spi));
|
||||
if (!master)
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*spi));
|
||||
if (!host)
|
||||
return dev_err_probe(&pdev->dev, -ENOMEM,
|
||||
"unable to allocate master for SPI controller\n");
|
||||
"unable to allocate host for SPI controller\n");
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
||||
if (of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs))
|
||||
num_cs = MAX_CS;
|
||||
|
||||
master->num_chipselect = num_cs;
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
|
||||
master->setup = mchp_corespi_setup;
|
||||
master->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
master->transfer_one = mchp_corespi_transfer_one;
|
||||
master->prepare_message = mchp_corespi_prepare_message;
|
||||
master->set_cs = mchp_corespi_set_cs;
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
host->num_chipselect = num_cs;
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
|
||||
host->setup = mchp_corespi_setup;
|
||||
host->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
host->transfer_one = mchp_corespi_transfer_one;
|
||||
host->prepare_message = mchp_corespi_prepare_message;
|
||||
host->set_cs = mchp_corespi_set_cs;
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
|
||||
spi = spi_master_get_devdata(master);
|
||||
spi = spi_controller_get_devdata(host);
|
||||
|
||||
spi->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
if (IS_ERR(spi->regs))
|
||||
@ -534,43 +534,36 @@ static int mchp_corespi_probe(struct platform_device *pdev)
|
||||
return spi->irq;
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, spi->irq, mchp_corespi_interrupt,
|
||||
IRQF_SHARED, dev_name(&pdev->dev), master);
|
||||
IRQF_SHARED, dev_name(&pdev->dev), host);
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret,
|
||||
"could not request irq\n");
|
||||
|
||||
spi->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
spi->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(spi->clk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(spi->clk),
|
||||
"could not get clk\n");
|
||||
|
||||
ret = clk_prepare_enable(spi->clk);
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret,
|
||||
"failed to enable clock\n");
|
||||
mchp_corespi_init(host, spi);
|
||||
|
||||
mchp_corespi_init(master, spi);
|
||||
|
||||
ret = devm_spi_register_master(&pdev->dev, master);
|
||||
ret = devm_spi_register_controller(&pdev->dev, host);
|
||||
if (ret) {
|
||||
mchp_corespi_disable(spi);
|
||||
clk_disable_unprepare(spi->clk);
|
||||
return dev_err_probe(&pdev->dev, ret,
|
||||
"unable to register master for SPI controller\n");
|
||||
"unable to register host for SPI controller\n");
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "Registered SPI controller %d\n", master->bus_num);
|
||||
dev_info(&pdev->dev, "Registered SPI controller %d\n", host->bus_num);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mchp_corespi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master = platform_get_drvdata(pdev);
|
||||
struct mchp_corespi *spi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct mchp_corespi *spi = spi_controller_get_devdata(host);
|
||||
|
||||
mchp_corespi_disable_ints(spi);
|
||||
clk_disable_unprepare(spi->clk);
|
||||
mchp_corespi_disable(spi);
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ static int mpc512x_psc_spi_transfer_setup(struct spi_device *spi,
|
||||
static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
|
||||
{
|
||||
struct mpc512x_psc_spi_cs *cs = spi->controller_state;
|
||||
struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
|
||||
struct mpc512x_psc_spi *mps = spi_controller_get_devdata(spi->controller);
|
||||
u32 sicr;
|
||||
u32 ccr;
|
||||
int speed;
|
||||
@ -143,7 +143,7 @@ static void mpc512x_psc_spi_deactivate_cs(struct spi_device *spi)
|
||||
static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi,
|
||||
struct spi_transfer *t)
|
||||
{
|
||||
struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
|
||||
struct mpc512x_psc_spi *mps = spi_controller_get_devdata(spi->controller);
|
||||
struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
|
||||
size_t tx_len = t->len;
|
||||
size_t rx_len = t->len;
|
||||
@ -280,7 +280,7 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpc512x_psc_spi_msg_xfer(struct spi_master *master,
|
||||
static int mpc512x_psc_spi_msg_xfer(struct spi_controller *host,
|
||||
struct spi_message *m)
|
||||
{
|
||||
struct spi_device *spi;
|
||||
@ -320,15 +320,15 @@ static int mpc512x_psc_spi_msg_xfer(struct spi_master *master,
|
||||
|
||||
mpc512x_psc_spi_transfer_setup(spi, NULL);
|
||||
|
||||
spi_finalize_current_message(master);
|
||||
spi_finalize_current_message(host);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master)
|
||||
static int mpc512x_psc_spi_prep_xfer_hw(struct spi_controller *host)
|
||||
{
|
||||
struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
|
||||
struct mpc512x_psc_spi *mps = spi_controller_get_devdata(host);
|
||||
|
||||
dev_dbg(&master->dev, "%s()\n", __func__);
|
||||
dev_dbg(&host->dev, "%s()\n", __func__);
|
||||
|
||||
/* Zero MR2 */
|
||||
in_8(psc_addr(mps, mr2));
|
||||
@ -340,12 +340,12 @@ static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpc512x_psc_spi_unprep_xfer_hw(struct spi_master *master)
|
||||
static int mpc512x_psc_spi_unprep_xfer_hw(struct spi_controller *host)
|
||||
{
|
||||
struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
|
||||
struct mpc512x_psc_spi *mps = spi_controller_get_devdata(host);
|
||||
struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
|
||||
|
||||
dev_dbg(&master->dev, "%s()\n", __func__);
|
||||
dev_dbg(&host->dev, "%s()\n", __func__);
|
||||
|
||||
/* disable transmitter/receiver and fifo interrupt */
|
||||
out_8(psc_addr(mps, command), MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
|
||||
@ -380,7 +380,7 @@ static void mpc512x_psc_spi_cleanup(struct spi_device *spi)
|
||||
kfree(spi->controller_state);
|
||||
}
|
||||
|
||||
static int mpc512x_psc_spi_port_config(struct spi_master *master,
|
||||
static int mpc512x_psc_spi_port_config(struct spi_controller *host,
|
||||
struct mpc512x_psc_spi *mps)
|
||||
{
|
||||
struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
|
||||
@ -408,7 +408,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
|
||||
sicr = 0x01000000 | /* SIM = 0001 -- 8 bit */
|
||||
0x00800000 | /* GenClk = 1 -- internal clk */
|
||||
0x00008000 | /* SPI = 1 */
|
||||
0x00004000 | /* MSTR = 1 -- SPI master */
|
||||
0x00004000 | /* MSTR = 1 -- SPI host */
|
||||
0x00000800; /* UseEOF = 1 -- SS low until EOF */
|
||||
|
||||
out_be32(psc_addr(mps, sicr), sicr);
|
||||
@ -459,28 +459,28 @@ static int mpc512x_psc_spi_of_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct mpc512x_psc_spi *mps;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
int ret;
|
||||
void *tempp;
|
||||
struct clk *clk;
|
||||
|
||||
master = devm_spi_alloc_master(dev, sizeof(*mps));
|
||||
if (master == NULL)
|
||||
host = devm_spi_alloc_host(dev, sizeof(*mps));
|
||||
if (host == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(dev, master);
|
||||
mps = spi_master_get_devdata(master);
|
||||
dev_set_drvdata(dev, host);
|
||||
mps = spi_controller_get_devdata(host);
|
||||
mps->type = (int)device_get_match_data(dev);
|
||||
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
|
||||
master->setup = mpc512x_psc_spi_setup;
|
||||
master->prepare_transfer_hardware = mpc512x_psc_spi_prep_xfer_hw;
|
||||
master->transfer_one_message = mpc512x_psc_spi_msg_xfer;
|
||||
master->unprepare_transfer_hardware = mpc512x_psc_spi_unprep_xfer_hw;
|
||||
master->use_gpio_descriptors = true;
|
||||
master->cleanup = mpc512x_psc_spi_cleanup;
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
|
||||
host->setup = mpc512x_psc_spi_setup;
|
||||
host->prepare_transfer_hardware = mpc512x_psc_spi_prep_xfer_hw;
|
||||
host->transfer_one_message = mpc512x_psc_spi_msg_xfer;
|
||||
host->unprepare_transfer_hardware = mpc512x_psc_spi_unprep_xfer_hw;
|
||||
host->use_gpio_descriptors = true;
|
||||
host->cleanup = mpc512x_psc_spi_cleanup;
|
||||
|
||||
device_set_node(&master->dev, dev_fwnode(dev));
|
||||
device_set_node(&host->dev, dev_fwnode(dev));
|
||||
|
||||
tempp = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
|
||||
if (IS_ERR(tempp))
|
||||
@ -509,11 +509,11 @@ static int mpc512x_psc_spi_of_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
|
||||
ret = mpc512x_psc_spi_port_config(master, mps);
|
||||
ret = mpc512x_psc_spi_port_config(host, mps);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return devm_spi_register_master(dev, master);
|
||||
return devm_spi_register_controller(dev, host);
|
||||
}
|
||||
|
||||
static const struct of_device_id mpc512x_psc_spi_of_match[] = {
|
||||
|
@ -60,7 +60,7 @@ static int mpc52xx_psc_spi_transfer_setup(struct spi_device *spi,
|
||||
static void mpc52xx_psc_spi_activate_cs(struct spi_device *spi)
|
||||
{
|
||||
struct mpc52xx_psc_spi_cs *cs = spi->controller_state;
|
||||
struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
|
||||
struct mpc52xx_psc_spi *mps = spi_controller_get_devdata(spi->controller);
|
||||
struct mpc52xx_psc __iomem *psc = mps->psc;
|
||||
u32 sicr;
|
||||
u16 ccr;
|
||||
@ -104,7 +104,7 @@ static void mpc52xx_psc_spi_activate_cs(struct spi_device *spi)
|
||||
static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi,
|
||||
struct spi_transfer *t)
|
||||
{
|
||||
struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
|
||||
struct mpc52xx_psc_spi *mps = spi_controller_get_devdata(spi->controller);
|
||||
struct mpc52xx_psc __iomem *psc = mps->psc;
|
||||
struct mpc52xx_psc_fifo __iomem *fifo = mps->fifo;
|
||||
unsigned rb = 0; /* number of bytes receieved */
|
||||
@ -175,8 +175,8 @@ static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mpc52xx_psc_spi_transfer_one_message(struct spi_controller *ctlr,
|
||||
struct spi_message *m)
|
||||
static int mpc52xx_psc_spi_transfer_one_message(struct spi_controller *ctlr,
|
||||
struct spi_message *m)
|
||||
{
|
||||
struct spi_device *spi;
|
||||
struct spi_transfer *t = NULL;
|
||||
@ -263,7 +263,7 @@ static int mpc52xx_psc_spi_port_config(int psc_id, struct mpc52xx_psc_spi *mps)
|
||||
out_8(&fifo->rfcntl, 0);
|
||||
out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL);
|
||||
|
||||
/* Configure 8bit codec mode as a SPI master and use EOF flags */
|
||||
/* Configure 8bit codec mode as a SPI host and use EOF flags */
|
||||
/* SICR_SIM_CODEC8|SICR_GENCLK|SICR_SPI|SICR_MSTR|SICR_USEEOF */
|
||||
out_be32(&psc->sicr, 0x0180C800);
|
||||
out_be16((u16 __iomem *)&psc->ccr, 0x070F); /* default SPI Clk 1MHz */
|
||||
@ -295,31 +295,31 @@ static int mpc52xx_psc_spi_of_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct mpc52xx_psc_spi *mps;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
u32 bus_num;
|
||||
int ret;
|
||||
|
||||
master = devm_spi_alloc_master(dev, sizeof(*mps));
|
||||
if (master == NULL)
|
||||
host = devm_spi_alloc_host(dev, sizeof(*mps));
|
||||
if (host == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(dev, master);
|
||||
mps = spi_master_get_devdata(master);
|
||||
dev_set_drvdata(dev, host);
|
||||
mps = spi_controller_get_devdata(host);
|
||||
|
||||
/* the spi->mode bits understood by this driver: */
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
|
||||
|
||||
ret = device_property_read_u32(dev, "cell-index", &bus_num);
|
||||
if (ret || bus_num > 5)
|
||||
return dev_err_probe(dev, ret ? : -EINVAL, "Invalid cell-index property\n");
|
||||
master->bus_num = bus_num + 1;
|
||||
host->bus_num = bus_num + 1;
|
||||
|
||||
master->num_chipselect = 255;
|
||||
master->setup = mpc52xx_psc_spi_setup;
|
||||
master->transfer_one_message = mpc52xx_psc_spi_transfer_one_message;
|
||||
master->cleanup = mpc52xx_psc_spi_cleanup;
|
||||
host->num_chipselect = 255;
|
||||
host->setup = mpc52xx_psc_spi_setup;
|
||||
host->transfer_one_message = mpc52xx_psc_spi_transfer_one_message;
|
||||
host->cleanup = mpc52xx_psc_spi_cleanup;
|
||||
|
||||
device_set_node(&master->dev, dev_fwnode(dev));
|
||||
device_set_node(&host->dev, dev_fwnode(dev));
|
||||
|
||||
mps->psc = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
|
||||
if (IS_ERR(mps->psc))
|
||||
@ -337,13 +337,13 @@ static int mpc52xx_psc_spi_of_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mpc52xx_psc_spi_port_config(master->bus_num, mps);
|
||||
ret = mpc52xx_psc_spi_port_config(host->bus_num, mps);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "can't configure PSC! Is it capable of SPI?\n");
|
||||
|
||||
init_completion(&mps->done);
|
||||
|
||||
return devm_spi_register_master(dev, master);
|
||||
return devm_spi_register_controller(dev, host);
|
||||
}
|
||||
|
||||
static const struct of_device_id mpc52xx_psc_spi_of_match[] = {
|
||||
|
@ -62,7 +62,7 @@ MODULE_LICENSE("GPL");
|
||||
|
||||
/* Driver internal data */
|
||||
struct mpc52xx_spi {
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
void __iomem *regs;
|
||||
int irq0; /* MODF irq */
|
||||
int irq1; /* SPIF irq */
|
||||
@ -152,7 +152,7 @@ mpc52xx_spi_fsmstate_idle(int irq, struct mpc52xx_spi *ms, u8 status, u8 data)
|
||||
u8 ctrl1;
|
||||
|
||||
if (status && irq)
|
||||
dev_err(&ms->master->dev, "spurious irq, status=0x%.2x\n",
|
||||
dev_err(&ms->host->dev, "spurious irq, status=0x%.2x\n",
|
||||
status);
|
||||
|
||||
/* Check if there is another transfer waiting. */
|
||||
@ -235,7 +235,7 @@ static int mpc52xx_spi_fsmstate_transfer(int irq, struct mpc52xx_spi *ms,
|
||||
return FSM_CONTINUE;
|
||||
} else if (status & SPI_STATUS_MODF) {
|
||||
ms->modf_count++;
|
||||
dev_err(&ms->master->dev, "mode fault\n");
|
||||
dev_err(&ms->host->dev, "mode fault\n");
|
||||
mpc52xx_spi_chipsel(ms, 0);
|
||||
ms->message->status = -EIO;
|
||||
if (ms->message->complete)
|
||||
@ -280,7 +280,7 @@ static int
|
||||
mpc52xx_spi_fsmstate_wait(int irq, struct mpc52xx_spi *ms, u8 status, u8 data)
|
||||
{
|
||||
if (status && irq)
|
||||
dev_err(&ms->master->dev, "spurious irq, status=0x%.2x\n",
|
||||
dev_err(&ms->host->dev, "spurious irq, status=0x%.2x\n",
|
||||
status);
|
||||
|
||||
if (((int)mftb()) - ms->timestamp < 0)
|
||||
@ -361,12 +361,12 @@ static void mpc52xx_spi_wq(struct work_struct *work)
|
||||
}
|
||||
|
||||
/*
|
||||
* spi_master ops
|
||||
* spi_controller ops
|
||||
*/
|
||||
|
||||
static int mpc52xx_spi_transfer(struct spi_device *spi, struct spi_message *m)
|
||||
{
|
||||
struct mpc52xx_spi *ms = spi_master_get_devdata(spi->master);
|
||||
struct mpc52xx_spi *ms = spi_controller_get_devdata(spi->controller);
|
||||
unsigned long flags;
|
||||
|
||||
m->actual_length = 0;
|
||||
@ -385,7 +385,7 @@ static int mpc52xx_spi_transfer(struct spi_device *spi, struct spi_message *m)
|
||||
*/
|
||||
static int mpc52xx_spi_probe(struct platform_device *op)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct mpc52xx_spi *ms;
|
||||
struct gpio_desc *gpio_cs;
|
||||
void __iomem *regs;
|
||||
@ -406,7 +406,7 @@ static int mpc52xx_spi_probe(struct platform_device *op)
|
||||
out_8(regs + SPI_PORTDATA, 0x8); /* Deassert /SS signal */
|
||||
|
||||
/* Clear the status register and re-read it to check for a MODF
|
||||
* failure. This driver cannot currently handle multiple masters
|
||||
* failure. This driver cannot currently handle multiple hosts
|
||||
* on the SPI bus. This fault will also occur if the SPI signals
|
||||
* are not connected to any pins (port_config setting) */
|
||||
in_8(regs + SPI_STATUS);
|
||||
@ -419,22 +419,22 @@ static int mpc52xx_spi_probe(struct platform_device *op)
|
||||
goto err_init;
|
||||
}
|
||||
|
||||
dev_dbg(&op->dev, "allocating spi_master struct\n");
|
||||
master = spi_alloc_master(&op->dev, sizeof(*ms));
|
||||
if (!master) {
|
||||
dev_dbg(&op->dev, "allocating spi_controller struct\n");
|
||||
host = spi_alloc_host(&op->dev, sizeof(*ms));
|
||||
if (!host) {
|
||||
rc = -ENOMEM;
|
||||
goto err_alloc;
|
||||
}
|
||||
|
||||
master->transfer = mpc52xx_spi_transfer;
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
|
||||
master->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
master->dev.of_node = op->dev.of_node;
|
||||
host->transfer = mpc52xx_spi_transfer;
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
|
||||
host->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
host->dev.of_node = op->dev.of_node;
|
||||
|
||||
platform_set_drvdata(op, master);
|
||||
platform_set_drvdata(op, host);
|
||||
|
||||
ms = spi_master_get_devdata(master);
|
||||
ms->master = master;
|
||||
ms = spi_controller_get_devdata(host);
|
||||
ms->host = host;
|
||||
ms->regs = regs;
|
||||
ms->irq0 = irq_of_parse_and_map(op->dev.of_node, 0);
|
||||
ms->irq1 = irq_of_parse_and_map(op->dev.of_node, 1);
|
||||
@ -442,7 +442,7 @@ static int mpc52xx_spi_probe(struct platform_device *op)
|
||||
ms->ipb_freq = mpc5xxx_get_bus_frequency(&op->dev);
|
||||
ms->gpio_cs_count = gpiod_count(&op->dev, NULL);
|
||||
if (ms->gpio_cs_count > 0) {
|
||||
master->num_chipselect = ms->gpio_cs_count;
|
||||
host->num_chipselect = ms->gpio_cs_count;
|
||||
ms->gpio_cs = kmalloc_array(ms->gpio_cs_count,
|
||||
sizeof(*ms->gpio_cs),
|
||||
GFP_KERNEL);
|
||||
@ -489,24 +489,24 @@ static int mpc52xx_spi_probe(struct platform_device *op)
|
||||
if (!ms->irq0)
|
||||
dev_info(&op->dev, "using polled mode\n");
|
||||
|
||||
dev_dbg(&op->dev, "registering spi_master struct\n");
|
||||
rc = spi_register_master(master);
|
||||
dev_dbg(&op->dev, "registering spi_controller struct\n");
|
||||
rc = spi_register_controller(host);
|
||||
if (rc)
|
||||
goto err_register;
|
||||
|
||||
dev_info(&ms->master->dev, "registered MPC5200 SPI bus\n");
|
||||
dev_info(&ms->host->dev, "registered MPC5200 SPI bus\n");
|
||||
|
||||
return rc;
|
||||
|
||||
err_register:
|
||||
dev_err(&ms->master->dev, "initialization failed\n");
|
||||
dev_err(&ms->host->dev, "initialization failed\n");
|
||||
err_gpio:
|
||||
while (i-- > 0)
|
||||
gpiod_put(ms->gpio_cs[i]);
|
||||
|
||||
kfree(ms->gpio_cs);
|
||||
err_alloc_gpio:
|
||||
spi_master_put(master);
|
||||
spi_controller_put(host);
|
||||
err_alloc:
|
||||
err_init:
|
||||
iounmap(regs);
|
||||
@ -515,8 +515,8 @@ static int mpc52xx_spi_probe(struct platform_device *op)
|
||||
|
||||
static void mpc52xx_spi_remove(struct platform_device *op)
|
||||
{
|
||||
struct spi_master *master = spi_master_get(platform_get_drvdata(op));
|
||||
struct mpc52xx_spi *ms = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = spi_controller_get(platform_get_drvdata(op));
|
||||
struct mpc52xx_spi *ms = spi_controller_get_devdata(host);
|
||||
int i;
|
||||
|
||||
free_irq(ms->irq0, ms);
|
||||
@ -526,9 +526,9 @@ static void mpc52xx_spi_remove(struct platform_device *op)
|
||||
gpiod_put(ms->gpio_cs[i]);
|
||||
|
||||
kfree(ms->gpio_cs);
|
||||
spi_unregister_master(master);
|
||||
spi_unregister_controller(host);
|
||||
iounmap(ms->regs);
|
||||
spi_master_put(master);
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
static const struct of_device_id mpc52xx_spi_match[] = {
|
||||
|
@ -135,7 +135,7 @@ struct mtk_spi_compatible {
|
||||
* @pad_num: Number of pad_sel entries
|
||||
* @pad_sel: Groups of pins to select
|
||||
* @parent_clk: Parent of sel_clk
|
||||
* @sel_clk: SPI master mux clock
|
||||
* @sel_clk: SPI host mux clock
|
||||
* @spi_clk: Peripheral clock
|
||||
* @spi_hclk: AHB bus clock
|
||||
* @cur_transfer: Currently processed SPI transfer
|
||||
@ -282,7 +282,7 @@ static void mtk_spi_reset(struct mtk_spi *mdata)
|
||||
|
||||
static int mtk_spi_set_hw_cs_timing(struct spi_device *spi)
|
||||
{
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(spi->master);
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(spi->controller);
|
||||
struct spi_delay *cs_setup = &spi->cs_setup;
|
||||
struct spi_delay *cs_hold = &spi->cs_hold;
|
||||
struct spi_delay *cs_inactive = &spi->cs_inactive;
|
||||
@ -347,13 +347,13 @@ static int mtk_spi_set_hw_cs_timing(struct spi_device *spi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_spi_hw_init(struct spi_master *master,
|
||||
static int mtk_spi_hw_init(struct spi_controller *host,
|
||||
struct spi_device *spi)
|
||||
{
|
||||
u16 cpha, cpol;
|
||||
u32 reg_val;
|
||||
struct mtk_chip_config *chip_config = spi->controller_data;
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(master);
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(host);
|
||||
|
||||
cpha = spi->mode & SPI_CPHA ? 1 : 0;
|
||||
cpol = spi->mode & SPI_CPOL ? 1 : 0;
|
||||
@ -452,16 +452,16 @@ static int mtk_spi_hw_init(struct spi_master *master,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_spi_prepare_message(struct spi_master *master,
|
||||
static int mtk_spi_prepare_message(struct spi_controller *host,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
return mtk_spi_hw_init(master, msg->spi);
|
||||
return mtk_spi_hw_init(host, msg->spi);
|
||||
}
|
||||
|
||||
static void mtk_spi_set_cs(struct spi_device *spi, bool enable)
|
||||
{
|
||||
u32 reg_val;
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(spi->master);
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
if (spi->mode & SPI_CS_HIGH)
|
||||
enable = !enable;
|
||||
@ -478,11 +478,11 @@ static void mtk_spi_set_cs(struct spi_device *spi, bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
static void mtk_spi_prepare_transfer(struct spi_master *master,
|
||||
static void mtk_spi_prepare_transfer(struct spi_controller *host,
|
||||
u32 speed_hz)
|
||||
{
|
||||
u32 div, sck_time, reg_val;
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(master);
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(host);
|
||||
|
||||
if (speed_hz < mdata->spi_clk_hz / 2)
|
||||
div = DIV_ROUND_UP(mdata->spi_clk_hz, speed_hz);
|
||||
@ -511,10 +511,10 @@ static void mtk_spi_prepare_transfer(struct spi_master *master,
|
||||
}
|
||||
}
|
||||
|
||||
static void mtk_spi_setup_packet(struct spi_master *master)
|
||||
static void mtk_spi_setup_packet(struct spi_controller *host)
|
||||
{
|
||||
u32 packet_size, packet_loop, reg_val;
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(master);
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(host);
|
||||
|
||||
if (mdata->dev_comp->ipm_design)
|
||||
packet_size = min_t(u32,
|
||||
@ -538,10 +538,10 @@ static void mtk_spi_setup_packet(struct spi_master *master)
|
||||
writel(reg_val, mdata->base + SPI_CFG1_REG);
|
||||
}
|
||||
|
||||
static void mtk_spi_enable_transfer(struct spi_master *master)
|
||||
static void mtk_spi_enable_transfer(struct spi_controller *host)
|
||||
{
|
||||
u32 cmd;
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(master);
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(host);
|
||||
|
||||
cmd = readl(mdata->base + SPI_CMD_REG);
|
||||
if (mdata->state == MTK_SPI_IDLE)
|
||||
@ -566,10 +566,10 @@ static int mtk_spi_get_mult_delta(struct mtk_spi *mdata, u32 xfer_len)
|
||||
return mult_delta;
|
||||
}
|
||||
|
||||
static void mtk_spi_update_mdata_len(struct spi_master *master)
|
||||
static void mtk_spi_update_mdata_len(struct spi_controller *host)
|
||||
{
|
||||
int mult_delta;
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(master);
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(host);
|
||||
|
||||
if (mdata->tx_sgl_len && mdata->rx_sgl_len) {
|
||||
if (mdata->tx_sgl_len > mdata->rx_sgl_len) {
|
||||
@ -594,10 +594,10 @@ static void mtk_spi_update_mdata_len(struct spi_master *master)
|
||||
}
|
||||
}
|
||||
|
||||
static void mtk_spi_setup_dma_addr(struct spi_master *master,
|
||||
static void mtk_spi_setup_dma_addr(struct spi_controller *host,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(master);
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(host);
|
||||
|
||||
if (mdata->tx_sgl) {
|
||||
writel((u32)(xfer->tx_dma & MTK_SPI_32BITS_MASK),
|
||||
@ -620,19 +620,19 @@ static void mtk_spi_setup_dma_addr(struct spi_master *master,
|
||||
}
|
||||
}
|
||||
|
||||
static int mtk_spi_fifo_transfer(struct spi_master *master,
|
||||
static int mtk_spi_fifo_transfer(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
int cnt, remainder;
|
||||
u32 reg_val;
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(master);
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(host);
|
||||
|
||||
mdata->cur_transfer = xfer;
|
||||
mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, xfer->len);
|
||||
mdata->num_xfered = 0;
|
||||
mtk_spi_prepare_transfer(master, xfer->speed_hz);
|
||||
mtk_spi_setup_packet(master);
|
||||
mtk_spi_prepare_transfer(host, xfer->speed_hz);
|
||||
mtk_spi_setup_packet(host);
|
||||
|
||||
if (xfer->tx_buf) {
|
||||
cnt = xfer->len / 4;
|
||||
@ -645,17 +645,17 @@ static int mtk_spi_fifo_transfer(struct spi_master *master,
|
||||
}
|
||||
}
|
||||
|
||||
mtk_spi_enable_transfer(master);
|
||||
mtk_spi_enable_transfer(host);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mtk_spi_dma_transfer(struct spi_master *master,
|
||||
static int mtk_spi_dma_transfer(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
int cmd;
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(master);
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(host);
|
||||
|
||||
mdata->tx_sgl = NULL;
|
||||
mdata->rx_sgl = NULL;
|
||||
@ -664,7 +664,7 @@ static int mtk_spi_dma_transfer(struct spi_master *master,
|
||||
mdata->cur_transfer = xfer;
|
||||
mdata->num_xfered = 0;
|
||||
|
||||
mtk_spi_prepare_transfer(master, xfer->speed_hz);
|
||||
mtk_spi_prepare_transfer(host, xfer->speed_hz);
|
||||
|
||||
cmd = readl(mdata->base + SPI_CMD_REG);
|
||||
if (xfer->tx_buf)
|
||||
@ -687,19 +687,19 @@ static int mtk_spi_dma_transfer(struct spi_master *master,
|
||||
mdata->rx_sgl_len = sg_dma_len(mdata->rx_sgl);
|
||||
}
|
||||
|
||||
mtk_spi_update_mdata_len(master);
|
||||
mtk_spi_setup_packet(master);
|
||||
mtk_spi_setup_dma_addr(master, xfer);
|
||||
mtk_spi_enable_transfer(master);
|
||||
mtk_spi_update_mdata_len(host);
|
||||
mtk_spi_setup_packet(host);
|
||||
mtk_spi_setup_dma_addr(host, xfer);
|
||||
mtk_spi_enable_transfer(host);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mtk_spi_transfer_one(struct spi_master *master,
|
||||
static int mtk_spi_transfer_one(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(spi->master);
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(spi->controller);
|
||||
u32 reg_val = 0;
|
||||
|
||||
/* prepare xfer direction and duplex mode */
|
||||
@ -712,13 +712,13 @@ static int mtk_spi_transfer_one(struct spi_master *master,
|
||||
writel(reg_val, mdata->base + SPI_CFG3_IPM_REG);
|
||||
}
|
||||
|
||||
if (master->can_dma(master, spi, xfer))
|
||||
return mtk_spi_dma_transfer(master, spi, xfer);
|
||||
if (host->can_dma(host, spi, xfer))
|
||||
return mtk_spi_dma_transfer(host, spi, xfer);
|
||||
else
|
||||
return mtk_spi_fifo_transfer(master, spi, xfer);
|
||||
return mtk_spi_fifo_transfer(host, spi, xfer);
|
||||
}
|
||||
|
||||
static bool mtk_spi_can_dma(struct spi_master *master,
|
||||
static bool mtk_spi_can_dma(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
@ -730,7 +730,7 @@ static bool mtk_spi_can_dma(struct spi_master *master,
|
||||
|
||||
static int mtk_spi_setup(struct spi_device *spi)
|
||||
{
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(spi->master);
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
if (!spi->controller_data)
|
||||
spi->controller_data = (void *)&mtk_default_chip_info;
|
||||
@ -745,8 +745,8 @@ static int mtk_spi_setup(struct spi_device *spi)
|
||||
static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
u32 cmd, reg_val, cnt, remainder, len;
|
||||
struct spi_master *master = dev_id;
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_id;
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(host);
|
||||
struct spi_transfer *trans = mdata->cur_transfer;
|
||||
|
||||
reg_val = readl(mdata->base + SPI_STATUS0_REG);
|
||||
@ -761,7 +761,7 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if (!master->can_dma(master, NULL, trans)) {
|
||||
if (!host->can_dma(host, NULL, trans)) {
|
||||
if (trans->rx_buf) {
|
||||
cnt = mdata->xfer_len / 4;
|
||||
ioread32_rep(mdata->base + SPI_RX_DATA_REG,
|
||||
@ -779,13 +779,13 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
|
||||
|
||||
mdata->num_xfered += mdata->xfer_len;
|
||||
if (mdata->num_xfered == trans->len) {
|
||||
spi_finalize_current_transfer(master);
|
||||
spi_finalize_current_transfer(host);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
len = trans->len - mdata->num_xfered;
|
||||
mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, len);
|
||||
mtk_spi_setup_packet(master);
|
||||
mtk_spi_setup_packet(host);
|
||||
|
||||
cnt = mdata->xfer_len / 4;
|
||||
iowrite32_rep(mdata->base + SPI_TX_DATA_REG,
|
||||
@ -800,7 +800,7 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
|
||||
writel(reg_val, mdata->base + SPI_TX_DATA_REG);
|
||||
}
|
||||
|
||||
mtk_spi_enable_transfer(master);
|
||||
mtk_spi_enable_transfer(host);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -832,14 +832,14 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
|
||||
cmd &= ~SPI_CMD_RX_DMA;
|
||||
writel(cmd, mdata->base + SPI_CMD_REG);
|
||||
|
||||
spi_finalize_current_transfer(master);
|
||||
spi_finalize_current_transfer(host);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
mtk_spi_update_mdata_len(master);
|
||||
mtk_spi_setup_packet(master);
|
||||
mtk_spi_setup_dma_addr(master, trans);
|
||||
mtk_spi_enable_transfer(master);
|
||||
mtk_spi_update_mdata_len(host);
|
||||
mtk_spi_setup_packet(host);
|
||||
mtk_spi_setup_dma_addr(host, trans);
|
||||
mtk_spi_enable_transfer(host);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -884,10 +884,10 @@ static bool mtk_spi_mem_supports_op(struct spi_mem *mem,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void mtk_spi_mem_setup_dma_xfer(struct spi_master *master,
|
||||
static void mtk_spi_mem_setup_dma_xfer(struct spi_controller *host,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(master);
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(host);
|
||||
|
||||
writel((u32)(mdata->tx_dma & MTK_SPI_32BITS_MASK),
|
||||
mdata->base + SPI_TX_SRC_REG);
|
||||
@ -911,7 +911,7 @@ static void mtk_spi_mem_setup_dma_xfer(struct spi_master *master,
|
||||
static int mtk_spi_transfer_wait(struct spi_mem *mem,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(mem->spi->master);
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(mem->spi->controller);
|
||||
/*
|
||||
* For each byte we wait for 8 cycles of the SPI clock.
|
||||
* Since speed is defined in Hz and we want milliseconds,
|
||||
@ -941,7 +941,7 @@ static int mtk_spi_transfer_wait(struct spi_mem *mem,
|
||||
static int mtk_spi_mem_exec_op(struct spi_mem *mem,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(mem->spi->master);
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(mem->spi->controller);
|
||||
u32 reg_val, nio, tx_size;
|
||||
char *tx_tmp_buf, *rx_tmp_buf;
|
||||
int ret = 0;
|
||||
@ -950,8 +950,8 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem,
|
||||
reinit_completion(&mdata->spimem_done);
|
||||
|
||||
mtk_spi_reset(mdata);
|
||||
mtk_spi_hw_init(mem->spi->master, mem->spi);
|
||||
mtk_spi_prepare_transfer(mem->spi->master, mem->spi->max_speed_hz);
|
||||
mtk_spi_hw_init(mem->spi->controller, mem->spi);
|
||||
mtk_spi_prepare_transfer(mem->spi->controller, mem->spi->max_speed_hz);
|
||||
|
||||
reg_val = readl(mdata->base + SPI_CFG3_IPM_REG);
|
||||
/* opcode byte len */
|
||||
@ -971,7 +971,7 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem,
|
||||
} else {
|
||||
reg_val &= ~SPI_CFG3_IPM_NODATA_FLAG;
|
||||
mdata->xfer_len = op->data.nbytes;
|
||||
mtk_spi_setup_packet(mem->spi->master);
|
||||
mtk_spi_setup_packet(mem->spi->controller);
|
||||
}
|
||||
|
||||
if (op->addr.nbytes || op->dummy.nbytes) {
|
||||
@ -1069,9 +1069,9 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem,
|
||||
reg_val |= SPI_CMD_RX_DMA;
|
||||
writel(reg_val, mdata->base + SPI_CMD_REG);
|
||||
|
||||
mtk_spi_mem_setup_dma_xfer(mem->spi->master, op);
|
||||
mtk_spi_mem_setup_dma_xfer(mem->spi->controller, op);
|
||||
|
||||
mtk_spi_enable_transfer(mem->spi->master);
|
||||
mtk_spi_enable_transfer(mem->spi->controller);
|
||||
|
||||
/* Wait for the interrupt. */
|
||||
ret = mtk_spi_transfer_wait(mem, op);
|
||||
@ -1115,41 +1115,41 @@ static const struct spi_controller_mem_ops mtk_spi_mem_ops = {
|
||||
static int mtk_spi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct mtk_spi *mdata;
|
||||
int i, irq, ret, addr_bits;
|
||||
|
||||
master = devm_spi_alloc_master(dev, sizeof(*mdata));
|
||||
if (!master)
|
||||
return dev_err_probe(dev, -ENOMEM, "failed to alloc spi master\n");
|
||||
host = devm_spi_alloc_host(dev, sizeof(*mdata));
|
||||
if (!host)
|
||||
return dev_err_probe(dev, -ENOMEM, "failed to alloc spi host\n");
|
||||
|
||||
master->auto_runtime_pm = true;
|
||||
master->dev.of_node = dev->of_node;
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
|
||||
host->auto_runtime_pm = true;
|
||||
host->dev.of_node = dev->of_node;
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
|
||||
|
||||
master->set_cs = mtk_spi_set_cs;
|
||||
master->prepare_message = mtk_spi_prepare_message;
|
||||
master->transfer_one = mtk_spi_transfer_one;
|
||||
master->can_dma = mtk_spi_can_dma;
|
||||
master->setup = mtk_spi_setup;
|
||||
master->set_cs_timing = mtk_spi_set_hw_cs_timing;
|
||||
master->use_gpio_descriptors = true;
|
||||
host->set_cs = mtk_spi_set_cs;
|
||||
host->prepare_message = mtk_spi_prepare_message;
|
||||
host->transfer_one = mtk_spi_transfer_one;
|
||||
host->can_dma = mtk_spi_can_dma;
|
||||
host->setup = mtk_spi_setup;
|
||||
host->set_cs_timing = mtk_spi_set_hw_cs_timing;
|
||||
host->use_gpio_descriptors = true;
|
||||
|
||||
mdata = spi_master_get_devdata(master);
|
||||
mdata = spi_controller_get_devdata(host);
|
||||
mdata->dev_comp = device_get_match_data(dev);
|
||||
|
||||
if (mdata->dev_comp->enhance_timing)
|
||||
master->mode_bits |= SPI_CS_HIGH;
|
||||
host->mode_bits |= SPI_CS_HIGH;
|
||||
|
||||
if (mdata->dev_comp->must_tx)
|
||||
master->flags = SPI_CONTROLLER_MUST_TX;
|
||||
host->flags = SPI_CONTROLLER_MUST_TX;
|
||||
if (mdata->dev_comp->ipm_design)
|
||||
master->mode_bits |= SPI_LOOP | SPI_RX_DUAL | SPI_TX_DUAL |
|
||||
SPI_RX_QUAD | SPI_TX_QUAD;
|
||||
host->mode_bits |= SPI_LOOP | SPI_RX_DUAL | SPI_TX_DUAL |
|
||||
SPI_RX_QUAD | SPI_TX_QUAD;
|
||||
|
||||
if (mdata->dev_comp->ipm_design) {
|
||||
mdata->dev = dev;
|
||||
master->mem_ops = &mtk_spi_mem_ops;
|
||||
host->mem_ops = &mtk_spi_mem_ops;
|
||||
init_completion(&mdata->spimem_done);
|
||||
}
|
||||
|
||||
@ -1176,7 +1176,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
platform_set_drvdata(pdev, host);
|
||||
mdata->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(mdata->base))
|
||||
return PTR_ERR(mdata->base);
|
||||
@ -1235,12 +1235,12 @@ static int mtk_spi_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
if (mdata->dev_comp->need_pad_sel) {
|
||||
if (mdata->pad_num != master->num_chipselect)
|
||||
if (mdata->pad_num != host->num_chipselect)
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"pad_num does not match num_chipselect(%d != %d)\n",
|
||||
mdata->pad_num, master->num_chipselect);
|
||||
mdata->pad_num, host->num_chipselect);
|
||||
|
||||
if (!master->cs_gpiods && master->num_chipselect > 1)
|
||||
if (!host->cs_gpiods && host->num_chipselect > 1)
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"cs_gpios not specified and num_chipselect > 1\n");
|
||||
}
|
||||
@ -1255,16 +1255,16 @@ static int mtk_spi_probe(struct platform_device *pdev)
|
||||
addr_bits, ret);
|
||||
|
||||
ret = devm_request_irq(dev, irq, mtk_spi_interrupt,
|
||||
IRQF_TRIGGER_NONE, dev_name(dev), master);
|
||||
IRQF_TRIGGER_NONE, dev_name(dev), host);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to register irq\n");
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
ret = devm_spi_register_master(dev, master);
|
||||
ret = devm_spi_register_controller(dev, host);
|
||||
if (ret) {
|
||||
pm_runtime_disable(dev);
|
||||
return dev_err_probe(dev, ret, "failed to register master\n");
|
||||
return dev_err_probe(dev, ret, "failed to register host\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1272,8 +1272,8 @@ static int mtk_spi_probe(struct platform_device *pdev)
|
||||
|
||||
static void mtk_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master = platform_get_drvdata(pdev);
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(host);
|
||||
int ret;
|
||||
|
||||
if (mdata->use_spimem && !completion_done(&mdata->spimem_done))
|
||||
@ -1304,10 +1304,10 @@ static void mtk_spi_remove(struct platform_device *pdev)
|
||||
static int mtk_spi_suspend(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(host);
|
||||
|
||||
ret = spi_master_suspend(master);
|
||||
ret = spi_controller_suspend(host);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -1322,8 +1322,8 @@ static int mtk_spi_suspend(struct device *dev)
|
||||
static int mtk_spi_resume(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(host);
|
||||
|
||||
if (!pm_runtime_suspended(dev)) {
|
||||
ret = clk_prepare_enable(mdata->spi_clk);
|
||||
@ -1340,7 +1340,7 @@ static int mtk_spi_resume(struct device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
ret = spi_master_resume(master);
|
||||
ret = spi_controller_resume(host);
|
||||
if (ret < 0) {
|
||||
clk_disable_unprepare(mdata->spi_clk);
|
||||
clk_disable_unprepare(mdata->spi_hclk);
|
||||
@ -1353,8 +1353,8 @@ static int mtk_spi_resume(struct device *dev)
|
||||
#ifdef CONFIG_PM
|
||||
static int mtk_spi_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(host);
|
||||
|
||||
if (mdata->dev_comp->no_need_unprepare) {
|
||||
clk_disable(mdata->spi_clk);
|
||||
@ -1369,8 +1369,8 @@ static int mtk_spi_runtime_suspend(struct device *dev)
|
||||
|
||||
static int mtk_spi_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct mtk_spi *mdata = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct mtk_spi *mdata = spi_controller_get_devdata(host);
|
||||
int ret;
|
||||
|
||||
if (mdata->dev_comp->no_need_unprepare) {
|
||||
|
@ -53,7 +53,7 @@
|
||||
#define MT7621_LSB_FIRST BIT(3)
|
||||
|
||||
struct mt7621_spi {
|
||||
struct spi_controller *master;
|
||||
struct spi_controller *host;
|
||||
void __iomem *base;
|
||||
unsigned int sys_freq;
|
||||
unsigned int speed;
|
||||
@ -62,7 +62,7 @@ struct mt7621_spi {
|
||||
|
||||
static inline struct mt7621_spi *spidev_to_mt7621_spi(struct spi_device *spi)
|
||||
{
|
||||
return spi_controller_get_devdata(spi->master);
|
||||
return spi_controller_get_devdata(spi->controller);
|
||||
}
|
||||
|
||||
static inline u32 mt7621_spi_read(struct mt7621_spi *rs, u32 reg)
|
||||
@ -80,17 +80,17 @@ static void mt7621_spi_set_cs(struct spi_device *spi, int enable)
|
||||
struct mt7621_spi *rs = spidev_to_mt7621_spi(spi);
|
||||
int cs = spi_get_chipselect(spi, 0);
|
||||
u32 polar = 0;
|
||||
u32 master;
|
||||
u32 host;
|
||||
|
||||
/*
|
||||
* Select SPI device 7, enable "more buffer mode" and disable
|
||||
* full-duplex (only half-duplex really works on this chip
|
||||
* reliably)
|
||||
*/
|
||||
master = mt7621_spi_read(rs, MT7621_SPI_MASTER);
|
||||
master |= MASTER_RS_SLAVE_SEL | MASTER_MORE_BUFMODE;
|
||||
master &= ~MASTER_FULL_DUPLEX;
|
||||
mt7621_spi_write(rs, MT7621_SPI_MASTER, master);
|
||||
host = mt7621_spi_read(rs, MT7621_SPI_MASTER);
|
||||
host |= MASTER_RS_SLAVE_SEL | MASTER_MORE_BUFMODE;
|
||||
host &= ~MASTER_FULL_DUPLEX;
|
||||
mt7621_spi_write(rs, MT7621_SPI_MASTER, host);
|
||||
|
||||
rs->pending_write = 0;
|
||||
|
||||
@ -245,10 +245,10 @@ static void mt7621_spi_write_half_duplex(struct mt7621_spi *rs,
|
||||
rs->pending_write = len;
|
||||
}
|
||||
|
||||
static int mt7621_spi_transfer_one_message(struct spi_controller *master,
|
||||
static int mt7621_spi_transfer_one_message(struct spi_controller *host,
|
||||
struct spi_message *m)
|
||||
{
|
||||
struct mt7621_spi *rs = spi_controller_get_devdata(master);
|
||||
struct mt7621_spi *rs = spi_controller_get_devdata(host);
|
||||
struct spi_device *spi = m->spi;
|
||||
unsigned int speed = spi->max_speed_hz;
|
||||
struct spi_transfer *t = NULL;
|
||||
@ -294,7 +294,7 @@ static int mt7621_spi_transfer_one_message(struct spi_controller *master,
|
||||
|
||||
msg_done:
|
||||
m->status = status;
|
||||
spi_finalize_current_message(master);
|
||||
spi_finalize_current_message(host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -325,7 +325,7 @@ MODULE_DEVICE_TABLE(of, mt7621_spi_match);
|
||||
static int mt7621_spi_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct of_device_id *match;
|
||||
struct spi_controller *master;
|
||||
struct spi_controller *host;
|
||||
struct mt7621_spi *rs;
|
||||
void __iomem *base;
|
||||
struct clk *clk;
|
||||
@ -344,25 +344,25 @@ static int mt7621_spi_probe(struct platform_device *pdev)
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(clk),
|
||||
"unable to get SYS clock\n");
|
||||
|
||||
master = devm_spi_alloc_master(&pdev->dev, sizeof(*rs));
|
||||
if (!master) {
|
||||
dev_info(&pdev->dev, "master allocation failed\n");
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*rs));
|
||||
if (!host) {
|
||||
dev_info(&pdev->dev, "host allocation failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
master->mode_bits = SPI_LSB_FIRST;
|
||||
master->flags = SPI_CONTROLLER_HALF_DUPLEX;
|
||||
master->setup = mt7621_spi_setup;
|
||||
master->transfer_one_message = mt7621_spi_transfer_one_message;
|
||||
master->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
master->num_chipselect = 2;
|
||||
host->mode_bits = SPI_LSB_FIRST;
|
||||
host->flags = SPI_CONTROLLER_HALF_DUPLEX;
|
||||
host->setup = mt7621_spi_setup;
|
||||
host->transfer_one_message = mt7621_spi_transfer_one_message;
|
||||
host->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
host->num_chipselect = 2;
|
||||
|
||||
dev_set_drvdata(&pdev->dev, master);
|
||||
dev_set_drvdata(&pdev->dev, host);
|
||||
|
||||
rs = spi_controller_get_devdata(master);
|
||||
rs = spi_controller_get_devdata(host);
|
||||
rs->base = base;
|
||||
rs->master = master;
|
||||
rs->host = host;
|
||||
rs->sys_freq = clk_get_rate(clk);
|
||||
rs->pending_write = 0;
|
||||
dev_info(&pdev->dev, "sys_freq: %u\n", rs->sys_freq);
|
||||
@ -373,7 +373,7 @@ static int mt7621_spi_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return devm_spi_register_controller(&pdev->dev, master);
|
||||
return devm_spi_register_controller(&pdev->dev, host);
|
||||
}
|
||||
|
||||
MODULE_ALIAS("platform:" DRIVER_NAME);
|
||||
|
@ -275,7 +275,7 @@ static void mtk_nor_adj_prg_size(struct spi_mem_op *op)
|
||||
|
||||
static int mtk_nor_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
|
||||
{
|
||||
struct mtk_nor *sp = spi_controller_get_devdata(mem->spi->master);
|
||||
struct mtk_nor *sp = spi_controller_get_devdata(mem->spi->controller);
|
||||
|
||||
if (!op->data.nbytes)
|
||||
return 0;
|
||||
@ -598,7 +598,7 @@ static int mtk_nor_spi_mem_prg(struct mtk_nor *sp, const struct spi_mem_op *op)
|
||||
|
||||
static int mtk_nor_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||
{
|
||||
struct mtk_nor *sp = spi_controller_get_devdata(mem->spi->master);
|
||||
struct mtk_nor *sp = spi_controller_get_devdata(mem->spi->controller);
|
||||
int ret;
|
||||
|
||||
if ((op->data.nbytes == 0) ||
|
||||
@ -639,7 +639,7 @@ static int mtk_nor_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||
|
||||
static int mtk_nor_setup(struct spi_device *spi)
|
||||
{
|
||||
struct mtk_nor *sp = spi_controller_get_devdata(spi->master);
|
||||
struct mtk_nor *sp = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
if (spi->max_speed_hz && (spi->max_speed_hz < sp->spi_freq)) {
|
||||
dev_err(&spi->dev, "spi clock should be %u Hz.\n",
|
||||
@ -651,10 +651,10 @@ static int mtk_nor_setup(struct spi_device *spi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_nor_transfer_one_message(struct spi_controller *master,
|
||||
static int mtk_nor_transfer_one_message(struct spi_controller *host,
|
||||
struct spi_message *m)
|
||||
{
|
||||
struct mtk_nor *sp = spi_controller_get_devdata(master);
|
||||
struct mtk_nor *sp = spi_controller_get_devdata(host);
|
||||
struct spi_transfer *t = NULL;
|
||||
unsigned long trx_len = 0;
|
||||
int stat = 0;
|
||||
@ -696,7 +696,7 @@ static int mtk_nor_transfer_one_message(struct spi_controller *master,
|
||||
m->actual_length = trx_len;
|
||||
msg_done:
|
||||
m->status = stat;
|
||||
spi_finalize_current_message(master);
|
||||
spi_finalize_current_message(host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -844,7 +844,7 @@ static int mtk_nor_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(*sp));
|
||||
ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*sp));
|
||||
if (!ctlr) {
|
||||
dev_err(&pdev->dev, "failed to allocate spi controller\n");
|
||||
return -ENOMEM;
|
||||
|
@ -1255,7 +1255,7 @@ static bool mtk_snand_supports_op(struct spi_mem *mem,
|
||||
|
||||
static int mtk_snand_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
|
||||
{
|
||||
struct mtk_snand *ms = spi_controller_get_devdata(mem->spi->master);
|
||||
struct mtk_snand *ms = spi_controller_get_devdata(mem->spi->controller);
|
||||
// page ops transfer size must be exactly ((sector_size + spare_size) *
|
||||
// nsectors). Limit the op size if the caller requests more than that.
|
||||
// exec_op will read more than needed and discard the leftover if the
|
||||
@ -1282,7 +1282,7 @@ static int mtk_snand_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
|
||||
|
||||
static int mtk_snand_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||
{
|
||||
struct mtk_snand *ms = spi_controller_get_devdata(mem->spi->master);
|
||||
struct mtk_snand *ms = spi_controller_get_devdata(mem->spi->controller);
|
||||
|
||||
dev_dbg(ms->dev, "OP %02x ADDR %08llX@%d:%u DATA %d:%u", op->cmd.opcode,
|
||||
op->addr.val, op->addr.buswidth, op->addr.nbytes,
|
||||
@ -1332,42 +1332,6 @@ static const struct of_device_id mtk_snand_ids[] = {
|
||||
|
||||
MODULE_DEVICE_TABLE(of, mtk_snand_ids);
|
||||
|
||||
static int mtk_snand_enable_clk(struct mtk_snand *ms)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(ms->nfi_clk);
|
||||
if (ret) {
|
||||
dev_err(ms->dev, "unable to enable nfi clk\n");
|
||||
return ret;
|
||||
}
|
||||
ret = clk_prepare_enable(ms->pad_clk);
|
||||
if (ret) {
|
||||
dev_err(ms->dev, "unable to enable pad clk\n");
|
||||
goto err1;
|
||||
}
|
||||
ret = clk_prepare_enable(ms->nfi_hclk);
|
||||
if (ret) {
|
||||
dev_err(ms->dev, "unable to enable nfi hclk\n");
|
||||
goto err2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
clk_disable_unprepare(ms->pad_clk);
|
||||
err1:
|
||||
clk_disable_unprepare(ms->nfi_clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mtk_snand_disable_clk(struct mtk_snand *ms)
|
||||
{
|
||||
clk_disable_unprepare(ms->nfi_hclk);
|
||||
clk_disable_unprepare(ms->pad_clk);
|
||||
clk_disable_unprepare(ms->nfi_clk);
|
||||
}
|
||||
|
||||
static int mtk_snand_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
@ -1382,7 +1346,7 @@ static int mtk_snand_probe(struct platform_device *pdev)
|
||||
if (!dev_id)
|
||||
return -EINVAL;
|
||||
|
||||
ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(*ms));
|
||||
ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*ms));
|
||||
if (!ctlr)
|
||||
return -ENOMEM;
|
||||
platform_set_drvdata(pdev, ctlr);
|
||||
@ -1406,49 +1370,45 @@ static int mtk_snand_probe(struct platform_device *pdev)
|
||||
|
||||
ms->dev = &pdev->dev;
|
||||
|
||||
ms->nfi_clk = devm_clk_get(&pdev->dev, "nfi_clk");
|
||||
ms->nfi_clk = devm_clk_get_enabled(&pdev->dev, "nfi_clk");
|
||||
if (IS_ERR(ms->nfi_clk)) {
|
||||
ret = PTR_ERR(ms->nfi_clk);
|
||||
dev_err(&pdev->dev, "unable to get nfi_clk, err = %d\n", ret);
|
||||
goto release_ecc;
|
||||
}
|
||||
|
||||
ms->pad_clk = devm_clk_get(&pdev->dev, "pad_clk");
|
||||
ms->pad_clk = devm_clk_get_enabled(&pdev->dev, "pad_clk");
|
||||
if (IS_ERR(ms->pad_clk)) {
|
||||
ret = PTR_ERR(ms->pad_clk);
|
||||
dev_err(&pdev->dev, "unable to get pad_clk, err = %d\n", ret);
|
||||
goto release_ecc;
|
||||
}
|
||||
|
||||
ms->nfi_hclk = devm_clk_get_optional(&pdev->dev, "nfi_hclk");
|
||||
ms->nfi_hclk = devm_clk_get_optional_enabled(&pdev->dev, "nfi_hclk");
|
||||
if (IS_ERR(ms->nfi_hclk)) {
|
||||
ret = PTR_ERR(ms->nfi_hclk);
|
||||
dev_err(&pdev->dev, "unable to get nfi_hclk, err = %d\n", ret);
|
||||
goto release_ecc;
|
||||
}
|
||||
|
||||
ret = mtk_snand_enable_clk(ms);
|
||||
if (ret)
|
||||
goto release_ecc;
|
||||
|
||||
init_completion(&ms->op_done);
|
||||
|
||||
ms->irq = platform_get_irq(pdev, 0);
|
||||
if (ms->irq < 0) {
|
||||
ret = ms->irq;
|
||||
goto disable_clk;
|
||||
goto release_ecc;
|
||||
}
|
||||
ret = devm_request_irq(ms->dev, ms->irq, mtk_snand_irq, 0x0,
|
||||
"mtk-snand", ms);
|
||||
if (ret) {
|
||||
dev_err(ms->dev, "failed to request snfi irq\n");
|
||||
goto disable_clk;
|
||||
goto release_ecc;
|
||||
}
|
||||
|
||||
ret = dma_set_mask(ms->dev, DMA_BIT_MASK(32));
|
||||
if (ret) {
|
||||
dev_err(ms->dev, "failed to set dma mask\n");
|
||||
goto disable_clk;
|
||||
goto release_ecc;
|
||||
}
|
||||
|
||||
// switch to SNFI mode
|
||||
@ -1472,7 +1432,7 @@ static int mtk_snand_probe(struct platform_device *pdev)
|
||||
ret = mtk_snand_setup_pagefmt(ms, SZ_2K, SZ_64);
|
||||
if (ret) {
|
||||
dev_err(ms->dev, "failed to set initial page format\n");
|
||||
goto disable_clk;
|
||||
goto release_ecc;
|
||||
}
|
||||
|
||||
// setup ECC engine
|
||||
@ -1484,7 +1444,7 @@ static int mtk_snand_probe(struct platform_device *pdev)
|
||||
ret = nand_ecc_register_on_host_hw_engine(&ms->ecc_eng);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register ecc engine.\n");
|
||||
goto disable_clk;
|
||||
goto release_ecc;
|
||||
}
|
||||
|
||||
ctlr->num_chipselect = 1;
|
||||
@ -1496,12 +1456,10 @@ static int mtk_snand_probe(struct platform_device *pdev)
|
||||
ret = spi_register_controller(ctlr);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "spi_register_controller failed.\n");
|
||||
goto disable_clk;
|
||||
goto release_ecc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
disable_clk:
|
||||
mtk_snand_disable_clk(ms);
|
||||
release_ecc:
|
||||
mtk_ecc_release(ms->ecc);
|
||||
return ret;
|
||||
@ -1513,7 +1471,6 @@ static void mtk_snand_remove(struct platform_device *pdev)
|
||||
struct mtk_snand *ms = spi_controller_get_devdata(ctlr);
|
||||
|
||||
spi_unregister_controller(ctlr);
|
||||
mtk_snand_disable_clk(ms);
|
||||
mtk_ecc_release(ms->ecc);
|
||||
kfree(ms->buf);
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ static int spi_mux_probe(struct spi_device *spi)
|
||||
struct spi_mux_priv *priv;
|
||||
int ret;
|
||||
|
||||
ctlr = spi_alloc_master(&spi->dev, sizeof(*priv));
|
||||
ctlr = spi_alloc_host(&spi->dev, sizeof(*priv));
|
||||
if (!ctlr)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -390,7 +390,7 @@ static int mxic_spi_data_xfer(struct mxic_spi *mxic, const void *txbuf,
|
||||
static ssize_t mxic_spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
||||
u64 offs, size_t len, void *buf)
|
||||
{
|
||||
struct mxic_spi *mxic = spi_master_get_devdata(desc->mem->spi->master);
|
||||
struct mxic_spi *mxic = spi_controller_get_devdata(desc->mem->spi->controller);
|
||||
int ret;
|
||||
u32 sts;
|
||||
|
||||
@ -434,7 +434,7 @@ static ssize_t mxic_spi_mem_dirmap_write(struct spi_mem_dirmap_desc *desc,
|
||||
u64 offs, size_t len,
|
||||
const void *buf)
|
||||
{
|
||||
struct mxic_spi *mxic = spi_master_get_devdata(desc->mem->spi->master);
|
||||
struct mxic_spi *mxic = spi_controller_get_devdata(desc->mem->spi->controller);
|
||||
u32 sts;
|
||||
int ret;
|
||||
|
||||
@ -493,7 +493,7 @@ static bool mxic_spi_mem_supports_op(struct spi_mem *mem,
|
||||
|
||||
static int mxic_spi_mem_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
||||
{
|
||||
struct mxic_spi *mxic = spi_master_get_devdata(desc->mem->spi->master);
|
||||
struct mxic_spi *mxic = spi_controller_get_devdata(desc->mem->spi->controller);
|
||||
|
||||
if (!mxic->linear.map)
|
||||
return -EINVAL;
|
||||
@ -510,7 +510,7 @@ static int mxic_spi_mem_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
||||
static int mxic_spi_mem_exec_op(struct spi_mem *mem,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
struct mxic_spi *mxic = spi_master_get_devdata(mem->spi->master);
|
||||
struct mxic_spi *mxic = spi_controller_get_devdata(mem->spi->controller);
|
||||
int i, ret;
|
||||
u8 addr[8], cmd[2];
|
||||
|
||||
@ -577,7 +577,7 @@ static const struct spi_controller_mem_caps mxic_spi_mem_caps = {
|
||||
|
||||
static void mxic_spi_set_cs(struct spi_device *spi, bool lvl)
|
||||
{
|
||||
struct mxic_spi *mxic = spi_master_get_devdata(spi->master);
|
||||
struct mxic_spi *mxic = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
if (!lvl) {
|
||||
writel(readl(mxic->regs + HC_CFG) | HC_CFG_MAN_CS_EN,
|
||||
@ -592,11 +592,11 @@ static void mxic_spi_set_cs(struct spi_device *spi, bool lvl)
|
||||
}
|
||||
}
|
||||
|
||||
static int mxic_spi_transfer_one(struct spi_master *master,
|
||||
static int mxic_spi_transfer_one(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *t)
|
||||
{
|
||||
struct mxic_spi *mxic = spi_master_get_devdata(master);
|
||||
struct mxic_spi *mxic = spi_controller_get_devdata(host);
|
||||
unsigned int busw = OP_BUSW_1;
|
||||
int ret;
|
||||
|
||||
@ -632,7 +632,7 @@ static int mxic_spi_transfer_one(struct spi_master *master,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
spi_finalize_current_transfer(master);
|
||||
spi_finalize_current_transfer(host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -713,8 +713,8 @@ static int mxic_spi_mem_ecc_probe(struct platform_device *pdev,
|
||||
|
||||
static int __maybe_unused mxic_spi_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct mxic_spi *mxic = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct mxic_spi *mxic = spi_controller_get_devdata(host);
|
||||
|
||||
mxic_spi_clk_disable(mxic);
|
||||
clk_disable_unprepare(mxic->ps_clk);
|
||||
@ -724,8 +724,8 @@ static int __maybe_unused mxic_spi_runtime_suspend(struct device *dev)
|
||||
|
||||
static int __maybe_unused mxic_spi_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct mxic_spi *mxic = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct mxic_spi *mxic = spi_controller_get_devdata(host);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(mxic->ps_clk);
|
||||
@ -744,21 +744,21 @@ static const struct dev_pm_ops mxic_spi_dev_pm_ops = {
|
||||
|
||||
static int mxic_spi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct resource *res;
|
||||
struct mxic_spi *mxic;
|
||||
int ret;
|
||||
|
||||
master = devm_spi_alloc_master(&pdev->dev, sizeof(struct mxic_spi));
|
||||
if (!master)
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(struct mxic_spi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
||||
mxic = spi_master_get_devdata(master);
|
||||
mxic = spi_controller_get_devdata(host);
|
||||
mxic->dev = &pdev->dev;
|
||||
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
|
||||
mxic->ps_clk = devm_clk_get(&pdev->dev, "ps_clk");
|
||||
if (IS_ERR(mxic->ps_clk))
|
||||
@ -786,19 +786,19 @@ static int mxic_spi_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
master->auto_runtime_pm = true;
|
||||
host->auto_runtime_pm = true;
|
||||
|
||||
master->num_chipselect = 1;
|
||||
master->mem_ops = &mxic_spi_mem_ops;
|
||||
master->mem_caps = &mxic_spi_mem_caps;
|
||||
host->num_chipselect = 1;
|
||||
host->mem_ops = &mxic_spi_mem_ops;
|
||||
host->mem_caps = &mxic_spi_mem_caps;
|
||||
|
||||
master->set_cs = mxic_spi_set_cs;
|
||||
master->transfer_one = mxic_spi_transfer_one;
|
||||
master->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA |
|
||||
SPI_RX_DUAL | SPI_TX_DUAL |
|
||||
SPI_RX_QUAD | SPI_TX_QUAD |
|
||||
SPI_RX_OCTAL | SPI_TX_OCTAL;
|
||||
host->set_cs = mxic_spi_set_cs;
|
||||
host->transfer_one = mxic_spi_transfer_one;
|
||||
host->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA |
|
||||
SPI_RX_DUAL | SPI_TX_DUAL |
|
||||
SPI_RX_QUAD | SPI_TX_QUAD |
|
||||
SPI_RX_OCTAL | SPI_TX_OCTAL;
|
||||
|
||||
mxic_spi_hw_init(mxic);
|
||||
|
||||
@ -808,9 +808,9 @@ static int mxic_spi_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = spi_register_master(master);
|
||||
ret = spi_register_controller(host);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "spi_register_master failed\n");
|
||||
dev_err(&pdev->dev, "spi_register_controller failed\n");
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
mxic_spi_mem_ecc_remove(mxic);
|
||||
}
|
||||
@ -820,12 +820,12 @@ static int mxic_spi_probe(struct platform_device *pdev)
|
||||
|
||||
static void mxic_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master = platform_get_drvdata(pdev);
|
||||
struct mxic_spi *mxic = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct mxic_spi *mxic = spi_controller_get_devdata(host);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
mxic_spi_mem_ecc_remove(mxic);
|
||||
spi_unregister_master(master);
|
||||
spi_unregister_controller(host);
|
||||
}
|
||||
|
||||
static const struct of_device_id mxic_spi_of_ids[] = {
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// Freescale MXS SPI master driver
|
||||
// Freescale MXS SPI host driver
|
||||
//
|
||||
// Copyright 2012 DENX Software Engineering, GmbH.
|
||||
// Copyright 2012 Freescale Semiconductor, Inc.
|
||||
@ -63,7 +63,7 @@ struct mxs_spi {
|
||||
static int mxs_spi_setup_transfer(struct spi_device *dev,
|
||||
const struct spi_transfer *t)
|
||||
{
|
||||
struct mxs_spi *spi = spi_master_get_devdata(dev->master);
|
||||
struct mxs_spi *spi = spi_controller_get_devdata(dev->controller);
|
||||
struct mxs_ssp *ssp = &spi->ssp;
|
||||
const unsigned int hz = min(dev->max_speed_hz, t->speed_hz);
|
||||
|
||||
@ -357,10 +357,10 @@ static int mxs_spi_txrx_pio(struct mxs_spi *spi,
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int mxs_spi_transfer_one(struct spi_master *master,
|
||||
static int mxs_spi_transfer_one(struct spi_controller *host,
|
||||
struct spi_message *m)
|
||||
{
|
||||
struct mxs_spi *spi = spi_master_get_devdata(master);
|
||||
struct mxs_spi *spi = spi_controller_get_devdata(host);
|
||||
struct mxs_ssp *ssp = &spi->ssp;
|
||||
struct spi_transfer *t;
|
||||
unsigned int flag;
|
||||
@ -432,15 +432,15 @@ static int mxs_spi_transfer_one(struct spi_master *master,
|
||||
}
|
||||
|
||||
m->status = status;
|
||||
spi_finalize_current_message(master);
|
||||
spi_finalize_current_message(host);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int mxs_spi_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct mxs_spi *spi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct mxs_spi *spi = spi_controller_get_devdata(host);
|
||||
struct mxs_ssp *ssp = &spi->ssp;
|
||||
int ret;
|
||||
|
||||
@ -460,8 +460,8 @@ static int mxs_spi_runtime_suspend(struct device *dev)
|
||||
|
||||
static int mxs_spi_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct mxs_spi *spi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct mxs_spi *spi = spi_controller_get_devdata(host);
|
||||
struct mxs_ssp *ssp = &spi->ssp;
|
||||
int ret;
|
||||
|
||||
@ -478,10 +478,10 @@ static int mxs_spi_runtime_resume(struct device *dev)
|
||||
|
||||
static int __maybe_unused mxs_spi_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = spi_master_suspend(master);
|
||||
ret = spi_controller_suspend(host);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -493,7 +493,7 @@ static int __maybe_unused mxs_spi_suspend(struct device *dev)
|
||||
|
||||
static int __maybe_unused mxs_spi_resume(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
if (!pm_runtime_suspended(dev))
|
||||
@ -503,7 +503,7 @@ static int __maybe_unused mxs_spi_resume(struct device *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = spi_master_resume(master);
|
||||
ret = spi_controller_resume(host);
|
||||
if (ret < 0 && !pm_runtime_suspended(dev))
|
||||
mxs_spi_runtime_suspend(dev);
|
||||
|
||||
@ -528,7 +528,7 @@ static int mxs_spi_probe(struct platform_device *pdev)
|
||||
const struct of_device_id *of_id =
|
||||
of_match_device(mxs_spi_dt_ids, &pdev->dev);
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct mxs_spi *spi;
|
||||
struct mxs_ssp *ssp;
|
||||
struct clk *clk;
|
||||
@ -561,21 +561,21 @@ static int mxs_spi_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
clk_freq = clk_freq_default;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(*spi));
|
||||
if (!master)
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*spi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
||||
master->transfer_one_message = mxs_spi_transfer_one;
|
||||
master->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA;
|
||||
master->num_chipselect = 3;
|
||||
master->dev.of_node = np;
|
||||
master->flags = SPI_CONTROLLER_HALF_DUPLEX;
|
||||
master->auto_runtime_pm = true;
|
||||
host->transfer_one_message = mxs_spi_transfer_one;
|
||||
host->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA;
|
||||
host->num_chipselect = 3;
|
||||
host->dev.of_node = np;
|
||||
host->flags = SPI_CONTROLLER_HALF_DUPLEX;
|
||||
host->auto_runtime_pm = true;
|
||||
|
||||
spi = spi_master_get_devdata(master);
|
||||
spi = spi_controller_get_devdata(host);
|
||||
ssp = &spi->ssp;
|
||||
ssp->dev = &pdev->dev;
|
||||
ssp->clk = clk;
|
||||
@ -587,13 +587,13 @@ 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_master_free;
|
||||
goto out_host_free;
|
||||
|
||||
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_master_free;
|
||||
goto out_host_free;
|
||||
}
|
||||
|
||||
pm_runtime_enable(ssp->dev);
|
||||
@ -617,9 +617,9 @@ static int mxs_spi_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
goto out_pm_runtime_put;
|
||||
|
||||
ret = devm_spi_register_master(&pdev->dev, master);
|
||||
ret = devm_spi_register_controller(&pdev->dev, host);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Cannot register SPI master, %d\n", ret);
|
||||
dev_err(&pdev->dev, "Cannot register SPI host, %d\n", ret);
|
||||
goto out_pm_runtime_put;
|
||||
}
|
||||
|
||||
@ -633,19 +633,19 @@ out_pm_runtime_disable:
|
||||
pm_runtime_disable(ssp->dev);
|
||||
out_dma_release:
|
||||
dma_release_channel(ssp->dmach);
|
||||
out_master_free:
|
||||
spi_master_put(master);
|
||||
out_host_free:
|
||||
spi_controller_put(host);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mxs_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct mxs_spi *spi;
|
||||
struct mxs_ssp *ssp;
|
||||
|
||||
master = platform_get_drvdata(pdev);
|
||||
spi = spi_master_get_devdata(master);
|
||||
host = platform_get_drvdata(pdev);
|
||||
spi = spi_controller_get_devdata(host);
|
||||
ssp = &spi->ssp;
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
@ -668,6 +668,6 @@ static struct platform_driver mxs_spi_driver = {
|
||||
module_platform_driver(mxs_spi_driver);
|
||||
|
||||
MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
|
||||
MODULE_DESCRIPTION("MXS SPI master driver");
|
||||
MODULE_DESCRIPTION("MXS SPI host driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:mxs-spi");
|
||||
|
@ -700,7 +700,7 @@ static int npcm_fiu_probe(struct platform_device *pdev)
|
||||
struct spi_controller *ctrl;
|
||||
struct npcm_fiu_spi *fiu;
|
||||
void __iomem *regbase;
|
||||
int id, ret;
|
||||
int id;
|
||||
|
||||
ctrl = devm_spi_alloc_host(dev, sizeof(*fiu));
|
||||
if (!ctrl)
|
||||
@ -738,7 +738,7 @@ static int npcm_fiu_probe(struct platform_device *pdev)
|
||||
|
||||
fiu->res_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||
"memory");
|
||||
fiu->clk = devm_clk_get(dev, NULL);
|
||||
fiu->clk = devm_clk_get_enabled(dev, NULL);
|
||||
if (IS_ERR(fiu->clk))
|
||||
return PTR_ERR(fiu->clk);
|
||||
|
||||
@ -746,7 +746,6 @@ static int npcm_fiu_probe(struct platform_device *pdev)
|
||||
"nuvoton,spix-mode");
|
||||
|
||||
platform_set_drvdata(pdev, fiu);
|
||||
clk_prepare_enable(fiu->clk);
|
||||
|
||||
ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD
|
||||
| SPI_TX_DUAL | SPI_TX_QUAD;
|
||||
@ -756,18 +755,11 @@ static int npcm_fiu_probe(struct platform_device *pdev)
|
||||
ctrl->num_chipselect = fiu->info->max_cs;
|
||||
ctrl->dev.of_node = dev->of_node;
|
||||
|
||||
ret = devm_spi_register_controller(dev, ctrl);
|
||||
if (ret)
|
||||
clk_disable_unprepare(fiu->clk);
|
||||
|
||||
return ret;
|
||||
return devm_spi_register_controller(dev, ctrl);
|
||||
}
|
||||
|
||||
static void npcm_fiu_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct npcm_fiu_spi *fiu = platform_get_drvdata(pdev);
|
||||
|
||||
clk_disable_unprepare(fiu->clk);
|
||||
}
|
||||
|
||||
MODULE_DEVICE_TABLE(of, npcm_fiu_dt_ids);
|
||||
|
@ -20,7 +20,7 @@
|
||||
struct npcm_pspi {
|
||||
struct completion xfer_done;
|
||||
struct reset_control *reset;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
unsigned int tx_bytes;
|
||||
unsigned int rx_bytes;
|
||||
void __iomem *base;
|
||||
@ -101,7 +101,7 @@ static inline void npcm_pspi_disable(struct npcm_pspi *priv)
|
||||
|
||||
static void npcm_pspi_set_mode(struct spi_device *spi)
|
||||
{
|
||||
struct npcm_pspi *priv = spi_master_get_devdata(spi->master);
|
||||
struct npcm_pspi *priv = spi_controller_get_devdata(spi->controller);
|
||||
u16 regtemp;
|
||||
u16 mode_val;
|
||||
|
||||
@ -159,7 +159,7 @@ static void npcm_pspi_set_baudrate(struct npcm_pspi *priv, unsigned int speed)
|
||||
static void npcm_pspi_setup_transfer(struct spi_device *spi,
|
||||
struct spi_transfer *t)
|
||||
{
|
||||
struct npcm_pspi *priv = spi_master_get_devdata(spi->master);
|
||||
struct npcm_pspi *priv = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
priv->tx_buf = t->tx_buf;
|
||||
priv->rx_buf = t->rx_buf;
|
||||
@ -245,11 +245,11 @@ static void npcm_pspi_recv(struct npcm_pspi *priv)
|
||||
}
|
||||
}
|
||||
|
||||
static int npcm_pspi_transfer_one(struct spi_master *master,
|
||||
static int npcm_pspi_transfer_one(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *t)
|
||||
{
|
||||
struct npcm_pspi *priv = spi_master_get_devdata(master);
|
||||
struct npcm_pspi *priv = spi_controller_get_devdata(host);
|
||||
int status;
|
||||
|
||||
npcm_pspi_setup_transfer(spi, t);
|
||||
@ -266,18 +266,18 @@ static int npcm_pspi_transfer_one(struct spi_master *master,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int npcm_pspi_prepare_transfer_hardware(struct spi_master *master)
|
||||
static int npcm_pspi_prepare_transfer_hardware(struct spi_controller *host)
|
||||
{
|
||||
struct npcm_pspi *priv = spi_master_get_devdata(master);
|
||||
struct npcm_pspi *priv = spi_controller_get_devdata(host);
|
||||
|
||||
npcm_pspi_irq_enable(priv, NPCM_PSPI_CTL1_EIR | NPCM_PSPI_CTL1_EIW);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int npcm_pspi_unprepare_transfer_hardware(struct spi_master *master)
|
||||
static int npcm_pspi_unprepare_transfer_hardware(struct spi_controller *host)
|
||||
{
|
||||
struct npcm_pspi *priv = spi_master_get_devdata(master);
|
||||
struct npcm_pspi *priv = spi_controller_get_devdata(host);
|
||||
|
||||
npcm_pspi_irq_disable(priv, NPCM_PSPI_CTL1_EIR | NPCM_PSPI_CTL1_EIW);
|
||||
|
||||
@ -340,37 +340,37 @@ static irqreturn_t npcm_pspi_handler(int irq, void *dev_id)
|
||||
static int npcm_pspi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct npcm_pspi *priv;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
unsigned long clk_hz;
|
||||
int irq;
|
||||
int ret;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(*priv));
|
||||
if (!master)
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*priv));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
||||
priv = spi_master_get_devdata(master);
|
||||
priv->master = master;
|
||||
priv = spi_controller_get_devdata(host);
|
||||
priv->host = host;
|
||||
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_master_put;
|
||||
goto out_host_put;
|
||||
}
|
||||
|
||||
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_master_put;
|
||||
goto out_host_put;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(priv->clk);
|
||||
if (ret)
|
||||
goto out_master_put;
|
||||
goto out_host_put;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
@ -398,42 +398,42 @@ static int npcm_pspi_probe(struct platform_device *pdev)
|
||||
|
||||
clk_hz = clk_get_rate(priv->clk);
|
||||
|
||||
master->max_speed_hz = DIV_ROUND_UP(clk_hz, NPCM_PSPI_MIN_CLK_DIVIDER);
|
||||
master->min_speed_hz = DIV_ROUND_UP(clk_hz, NPCM_PSPI_MAX_CLK_DIVIDER);
|
||||
master->mode_bits = SPI_CPHA | SPI_CPOL;
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
master->bus_num = -1;
|
||||
master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
|
||||
master->transfer_one = npcm_pspi_transfer_one;
|
||||
master->prepare_transfer_hardware =
|
||||
host->max_speed_hz = DIV_ROUND_UP(clk_hz, NPCM_PSPI_MIN_CLK_DIVIDER);
|
||||
host->min_speed_hz = DIV_ROUND_UP(clk_hz, NPCM_PSPI_MAX_CLK_DIVIDER);
|
||||
host->mode_bits = SPI_CPHA | SPI_CPOL;
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
host->bus_num = -1;
|
||||
host->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
|
||||
host->transfer_one = npcm_pspi_transfer_one;
|
||||
host->prepare_transfer_hardware =
|
||||
npcm_pspi_prepare_transfer_hardware;
|
||||
master->unprepare_transfer_hardware =
|
||||
host->unprepare_transfer_hardware =
|
||||
npcm_pspi_unprepare_transfer_hardware;
|
||||
master->use_gpio_descriptors = true;
|
||||
host->use_gpio_descriptors = true;
|
||||
|
||||
/* set to default clock rate */
|
||||
npcm_pspi_set_baudrate(priv, NPCM_PSPI_DEFAULT_CLK);
|
||||
|
||||
ret = devm_spi_register_master(&pdev->dev, master);
|
||||
ret = devm_spi_register_controller(&pdev->dev, host);
|
||||
if (ret)
|
||||
goto out_disable_clk;
|
||||
|
||||
pr_info("NPCM Peripheral SPI %d probed\n", master->bus_num);
|
||||
pr_info("NPCM Peripheral SPI %d probed\n", host->bus_num);
|
||||
|
||||
return 0;
|
||||
|
||||
out_disable_clk:
|
||||
clk_disable_unprepare(priv->clk);
|
||||
|
||||
out_master_put:
|
||||
spi_master_put(master);
|
||||
out_host_put:
|
||||
spi_controller_put(host);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void npcm_pspi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master = platform_get_drvdata(pdev);
|
||||
struct npcm_pspi *priv = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct npcm_pspi *priv = spi_controller_get_devdata(host);
|
||||
|
||||
npcm_pspi_reset_hw(priv);
|
||||
clk_disable_unprepare(priv->clk);
|
||||
|
@ -451,7 +451,7 @@ static int nxp_fspi_check_buswidth(struct nxp_fspi *f, u8 width)
|
||||
static bool nxp_fspi_supports_op(struct spi_mem *mem,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->master);
|
||||
struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->controller);
|
||||
int ret;
|
||||
|
||||
ret = nxp_fspi_check_buswidth(f, op->cmd.buswidth);
|
||||
@ -520,7 +520,7 @@ static int fspi_readl_poll_tout(struct nxp_fspi *f, void __iomem *base,
|
||||
}
|
||||
|
||||
/*
|
||||
* If the slave device content being changed by Write/Erase, need to
|
||||
* If the target device content being changed by Write/Erase, need to
|
||||
* invalidate the AHB buffer. This can be achieved by doing the reset
|
||||
* of controller after setting MCR0[SWRESET] bit.
|
||||
*/
|
||||
@ -661,7 +661,7 @@ static void nxp_fspi_dll_calibration(struct nxp_fspi *f)
|
||||
|
||||
/*
|
||||
* In FlexSPI controller, flash access is based on value of FSPI_FLSHXXCR0
|
||||
* register and start base address of the slave device.
|
||||
* register and start base address of the target device.
|
||||
*
|
||||
* (Higher address)
|
||||
* -------- <-- FLSHB2CR0
|
||||
@ -680,15 +680,15 @@ static void nxp_fspi_dll_calibration(struct nxp_fspi *f)
|
||||
*
|
||||
*
|
||||
* Start base address defines the starting address range for given CS and
|
||||
* FSPI_FLSHXXCR0 defines the size of the slave device connected at given CS.
|
||||
* FSPI_FLSHXXCR0 defines the size of the target device connected at given CS.
|
||||
*
|
||||
* But, different targets are having different combinations of number of CS,
|
||||
* some targets only have single CS or two CS covering controller's full
|
||||
* memory mapped space area.
|
||||
* Thus, implementation is being done as independent of the size and number
|
||||
* of the connected slave device.
|
||||
* of the connected target device.
|
||||
* Assign controller memory mapped space size as the size to the connected
|
||||
* slave device.
|
||||
* target device.
|
||||
* Mark FLSHxxCR0 as zero initially and then assign value only to the selected
|
||||
* chip-select Flash configuration register.
|
||||
*
|
||||
@ -704,8 +704,8 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi)
|
||||
uint64_t size_kb;
|
||||
|
||||
/*
|
||||
* Return, if previously selected slave device is same as current
|
||||
* requested slave device.
|
||||
* Return, if previously selected target device is same as current
|
||||
* requested target device.
|
||||
*/
|
||||
if (f->selected == spi_get_chipselect(spi, 0))
|
||||
return;
|
||||
@ -722,7 +722,7 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi)
|
||||
fspi_writel(f, size_kb, f->iobase + FSPI_FLSHA1CR0 +
|
||||
4 * spi_get_chipselect(spi, 0));
|
||||
|
||||
dev_dbg(f->dev, "Slave device [CS:%x] selected\n", spi_get_chipselect(spi, 0));
|
||||
dev_dbg(f->dev, "Target device [CS:%x] selected\n", spi_get_chipselect(spi, 0));
|
||||
|
||||
nxp_fspi_clk_disable_unprep(f);
|
||||
|
||||
@ -759,7 +759,7 @@ static int nxp_fspi_read_ahb(struct nxp_fspi *f, const struct spi_mem_op *op)
|
||||
f->memmap_len = len > NXP_FSPI_MIN_IOMAP ?
|
||||
len : NXP_FSPI_MIN_IOMAP;
|
||||
|
||||
f->ahb_addr = ioremap_wc(f->memmap_phy + f->memmap_start,
|
||||
f->ahb_addr = ioremap(f->memmap_phy + f->memmap_start,
|
||||
f->memmap_len);
|
||||
|
||||
if (!f->ahb_addr) {
|
||||
@ -912,7 +912,7 @@ static int nxp_fspi_do_op(struct nxp_fspi *f, const struct spi_mem_op *op)
|
||||
|
||||
static int nxp_fspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||
{
|
||||
struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->master);
|
||||
struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->controller);
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&f->lock);
|
||||
@ -952,7 +952,7 @@ static int nxp_fspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||
|
||||
static int nxp_fspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
|
||||
{
|
||||
struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->master);
|
||||
struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->controller);
|
||||
|
||||
if (op->data.dir == SPI_MEM_DATA_OUT) {
|
||||
if (op->data.nbytes > f->devtype_data->txfifo)
|
||||
@ -1049,7 +1049,7 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f)
|
||||
fspi_writel(f, FSPI_MCR0_MDIS, base + FSPI_MCR0);
|
||||
|
||||
/*
|
||||
* Config the DLL register to default value, enable the slave clock delay
|
||||
* Config the DLL register to default value, enable the target clock delay
|
||||
* line delay cell override mode, and use 1 fixed delay cell in DLL delay
|
||||
* chain, this is the suggested setting when clock rate < 100MHz.
|
||||
*/
|
||||
@ -1062,7 +1062,7 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f)
|
||||
base + FSPI_MCR0);
|
||||
|
||||
/*
|
||||
* Disable same device enable bit and configure all slave devices
|
||||
* Disable same device enable bit and configure all target devices
|
||||
* independently.
|
||||
*/
|
||||
reg = fspi_readl(f, f->iobase + FSPI_MCR2);
|
||||
@ -1107,7 +1107,7 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f)
|
||||
|
||||
static const char *nxp_fspi_get_name(struct spi_mem *mem)
|
||||
{
|
||||
struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->master);
|
||||
struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->controller);
|
||||
struct device *dev = &mem->spi->dev;
|
||||
const char *name;
|
||||
|
||||
@ -1144,7 +1144,7 @@ static int nxp_fspi_probe(struct platform_device *pdev)
|
||||
int ret;
|
||||
u32 reg;
|
||||
|
||||
ctlr = spi_alloc_master(&pdev->dev, sizeof(*f));
|
||||
ctlr = spi_alloc_host(&pdev->dev, sizeof(*f));
|
||||
if (!ctlr)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* OpenCores tiny SPI master driver
|
||||
* OpenCores tiny SPI host driver
|
||||
*
|
||||
* https://opencores.org/project,tiny_spi
|
||||
*
|
||||
@ -53,7 +53,7 @@ struct tiny_spi {
|
||||
|
||||
static inline struct tiny_spi *tiny_spi_to_hw(struct spi_device *sdev)
|
||||
{
|
||||
return spi_master_get_devdata(sdev->master);
|
||||
return spi_controller_get_devdata(sdev->controller);
|
||||
}
|
||||
|
||||
static unsigned int tiny_spi_baud(struct spi_device *spi, unsigned int hz)
|
||||
@ -212,24 +212,24 @@ static int tiny_spi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tiny_spi_platform_data *platp = dev_get_platdata(&pdev->dev);
|
||||
struct tiny_spi *hw;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
int err = -ENODEV;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(struct tiny_spi));
|
||||
if (!master)
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(struct tiny_spi));
|
||||
if (!host)
|
||||
return err;
|
||||
|
||||
/* setup the master state. */
|
||||
master->bus_num = pdev->id;
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
|
||||
master->setup = tiny_spi_setup;
|
||||
master->use_gpio_descriptors = true;
|
||||
/* setup the host state. */
|
||||
host->bus_num = pdev->id;
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
|
||||
host->setup = tiny_spi_setup;
|
||||
host->use_gpio_descriptors = true;
|
||||
|
||||
hw = spi_master_get_devdata(master);
|
||||
hw = spi_controller_get_devdata(host);
|
||||
platform_set_drvdata(pdev, hw);
|
||||
|
||||
/* setup the state for the bitbang driver */
|
||||
hw->bitbang.master = master;
|
||||
hw->bitbang.master = host;
|
||||
hw->bitbang.setup_transfer = tiny_spi_setup_transfer;
|
||||
hw->bitbang.txrx_bufs = tiny_spi_txrx_bufs;
|
||||
|
||||
@ -267,17 +267,17 @@ static int tiny_spi_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
|
||||
exit:
|
||||
spi_master_put(master);
|
||||
spi_controller_put(host);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void tiny_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tiny_spi *hw = platform_get_drvdata(pdev);
|
||||
struct spi_master *master = hw->bitbang.master;
|
||||
struct spi_controller *host = hw->bitbang.master;
|
||||
|
||||
spi_bitbang_stop(&hw->bitbang);
|
||||
spi_master_put(master);
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
@ -315,7 +315,7 @@ static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
|
||||
int div2;
|
||||
int status;
|
||||
|
||||
uwire = spi_master_get_devdata(spi->master);
|
||||
uwire = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
/* mode 0..3, clock inverted separately;
|
||||
* standard nCS signaling;
|
||||
@ -448,25 +448,25 @@ static void uwire_off(struct uwire_spi *uwire)
|
||||
{
|
||||
uwire_write_reg(UWIRE_SR3, 0);
|
||||
clk_disable_unprepare(uwire->ck);
|
||||
spi_master_put(uwire->bitbang.master);
|
||||
spi_controller_put(uwire->bitbang.master);
|
||||
}
|
||||
|
||||
static int uwire_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct uwire_spi *uwire;
|
||||
int status;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(*uwire));
|
||||
if (!master)
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*uwire));
|
||||
if (!host)
|
||||
return -ENODEV;
|
||||
|
||||
uwire = spi_master_get_devdata(master);
|
||||
uwire = spi_controller_get_devdata(host);
|
||||
|
||||
uwire_base = devm_ioremap(&pdev->dev, UWIRE_BASE_PHYS, UWIRE_IO_SIZE);
|
||||
if (!uwire_base) {
|
||||
dev_dbg(&pdev->dev, "can't ioremap UWIRE\n");
|
||||
spi_master_put(master);
|
||||
spi_controller_put(host);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -476,7 +476,7 @@ static int uwire_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(uwire->ck)) {
|
||||
status = PTR_ERR(uwire->ck);
|
||||
dev_dbg(&pdev->dev, "no functional clock?\n");
|
||||
spi_master_put(master);
|
||||
spi_controller_put(host);
|
||||
return status;
|
||||
}
|
||||
clk_prepare_enable(uwire->ck);
|
||||
@ -484,16 +484,16 @@ static int uwire_probe(struct platform_device *pdev)
|
||||
uwire_write_reg(UWIRE_SR3, 1);
|
||||
|
||||
/* the spi->mode bits understood by this driver: */
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
|
||||
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16);
|
||||
master->flags = SPI_CONTROLLER_HALF_DUPLEX;
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
|
||||
host->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16);
|
||||
host->flags = SPI_CONTROLLER_HALF_DUPLEX;
|
||||
|
||||
master->bus_num = 2; /* "official" */
|
||||
master->num_chipselect = 4;
|
||||
master->setup = uwire_setup;
|
||||
master->cleanup = uwire_cleanup;
|
||||
host->bus_num = 2; /* "official" */
|
||||
host->num_chipselect = 4;
|
||||
host->setup = uwire_setup;
|
||||
host->cleanup = uwire_cleanup;
|
||||
|
||||
uwire->bitbang.master = master;
|
||||
uwire->bitbang.master = host;
|
||||
uwire->bitbang.chipselect = uwire_chipselect;
|
||||
uwire->bitbang.setup_transfer = uwire_setup_transfer;
|
||||
uwire->bitbang.txrx_bufs = uwire_txrx;
|
||||
|
@ -53,6 +53,8 @@
|
||||
|
||||
/* per-register bitmasks: */
|
||||
#define OMAP2_MCSPI_IRQSTATUS_EOW BIT(17)
|
||||
#define OMAP2_MCSPI_IRQSTATUS_TX0_EMPTY BIT(0)
|
||||
#define OMAP2_MCSPI_IRQSTATUS_RX0_FULL BIT(2)
|
||||
|
||||
#define OMAP2_MCSPI_MODULCTRL_SINGLE BIT(0)
|
||||
#define OMAP2_MCSPI_MODULCTRL_MS BIT(2)
|
||||
@ -117,7 +119,7 @@ struct omap2_mcspi_regs {
|
||||
|
||||
struct omap2_mcspi {
|
||||
struct completion txdone;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *ctlr;
|
||||
/* Virtual base address of the controller */
|
||||
void __iomem *base;
|
||||
unsigned long phys;
|
||||
@ -125,10 +127,12 @@ struct omap2_mcspi {
|
||||
struct omap2_mcspi_dma *dma_channels;
|
||||
struct device *dev;
|
||||
struct omap2_mcspi_regs ctx;
|
||||
struct clk *ref_clk;
|
||||
int fifo_depth;
|
||||
bool slave_aborted;
|
||||
bool target_aborted;
|
||||
unsigned int pin_dir:1;
|
||||
size_t max_xfer_len;
|
||||
u32 ref_clk_hz;
|
||||
};
|
||||
|
||||
struct omap2_mcspi_cs {
|
||||
@ -141,17 +145,17 @@ struct omap2_mcspi_cs {
|
||||
u32 chconf0, chctrl0;
|
||||
};
|
||||
|
||||
static inline void mcspi_write_reg(struct spi_master *master,
|
||||
static inline void mcspi_write_reg(struct spi_controller *ctlr,
|
||||
int idx, u32 val)
|
||||
{
|
||||
struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
|
||||
struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr);
|
||||
|
||||
writel_relaxed(val, mcspi->base + idx);
|
||||
}
|
||||
|
||||
static inline u32 mcspi_read_reg(struct spi_master *master, int idx)
|
||||
static inline u32 mcspi_read_reg(struct spi_controller *ctlr, int idx)
|
||||
{
|
||||
struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
|
||||
struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr);
|
||||
|
||||
return readl_relaxed(mcspi->base + idx);
|
||||
}
|
||||
@ -235,7 +239,7 @@ static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
|
||||
|
||||
static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable)
|
||||
{
|
||||
struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master);
|
||||
struct omap2_mcspi *mcspi = spi_controller_get_devdata(spi->controller);
|
||||
u32 l;
|
||||
|
||||
/* The controller handles the inverted chip selects
|
||||
@ -266,39 +270,39 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
static void omap2_mcspi_set_mode(struct spi_master *master)
|
||||
static void omap2_mcspi_set_mode(struct spi_controller *ctlr)
|
||||
{
|
||||
struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
|
||||
struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr);
|
||||
struct omap2_mcspi_regs *ctx = &mcspi->ctx;
|
||||
u32 l;
|
||||
|
||||
/*
|
||||
* Choose master or slave mode
|
||||
* Choose host or target mode
|
||||
*/
|
||||
l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL);
|
||||
l = mcspi_read_reg(ctlr, OMAP2_MCSPI_MODULCTRL);
|
||||
l &= ~(OMAP2_MCSPI_MODULCTRL_STEST);
|
||||
if (spi_controller_is_slave(master)) {
|
||||
if (spi_controller_is_target(ctlr)) {
|
||||
l |= (OMAP2_MCSPI_MODULCTRL_MS);
|
||||
} else {
|
||||
l &= ~(OMAP2_MCSPI_MODULCTRL_MS);
|
||||
l |= OMAP2_MCSPI_MODULCTRL_SINGLE;
|
||||
}
|
||||
mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l);
|
||||
mcspi_write_reg(ctlr, OMAP2_MCSPI_MODULCTRL, l);
|
||||
|
||||
ctx->modulctrl = l;
|
||||
}
|
||||
|
||||
static void omap2_mcspi_set_fifo(const struct spi_device *spi,
|
||||
struct spi_transfer *t, int enable)
|
||||
struct spi_transfer *t, int enable, int dma_enabled)
|
||||
{
|
||||
struct spi_master *master = spi->master;
|
||||
struct spi_controller *ctlr = spi->controller;
|
||||
struct omap2_mcspi_cs *cs = spi->controller_state;
|
||||
struct omap2_mcspi *mcspi;
|
||||
unsigned int wcnt;
|
||||
int max_fifo_depth, bytes_per_word;
|
||||
u32 chconf, xferlevel;
|
||||
|
||||
mcspi = spi_master_get_devdata(master);
|
||||
mcspi = spi_controller_get_devdata(ctlr);
|
||||
|
||||
chconf = mcspi_cached_chconf0(spi);
|
||||
if (enable) {
|
||||
@ -310,23 +314,31 @@ static void omap2_mcspi_set_fifo(const struct spi_device *spi,
|
||||
max_fifo_depth = OMAP2_MCSPI_MAX_FIFODEPTH / 2;
|
||||
else
|
||||
max_fifo_depth = OMAP2_MCSPI_MAX_FIFODEPTH;
|
||||
|
||||
wcnt = t->len / bytes_per_word;
|
||||
if (dma_enabled)
|
||||
wcnt = t->len / bytes_per_word;
|
||||
else
|
||||
wcnt = 0;
|
||||
if (wcnt > OMAP2_MCSPI_MAX_FIFOWCNT)
|
||||
goto disable_fifo;
|
||||
|
||||
xferlevel = wcnt << 16;
|
||||
if (t->rx_buf != NULL) {
|
||||
chconf |= OMAP2_MCSPI_CHCONF_FFER;
|
||||
xferlevel |= (bytes_per_word - 1) << 8;
|
||||
if (dma_enabled)
|
||||
xferlevel |= (bytes_per_word - 1) << 8;
|
||||
else
|
||||
xferlevel |= (max_fifo_depth - 1) << 8;
|
||||
}
|
||||
|
||||
if (t->tx_buf != NULL) {
|
||||
chconf |= OMAP2_MCSPI_CHCONF_FFET;
|
||||
xferlevel |= bytes_per_word - 1;
|
||||
if (dma_enabled)
|
||||
xferlevel |= bytes_per_word - 1;
|
||||
else
|
||||
xferlevel |= (max_fifo_depth - 1);
|
||||
}
|
||||
|
||||
mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL, xferlevel);
|
||||
mcspi_write_reg(ctlr, OMAP2_MCSPI_XFERLEVEL, xferlevel);
|
||||
mcspi_write_chconf0(spi, chconf);
|
||||
mcspi->fifo_depth = max_fifo_depth;
|
||||
|
||||
@ -364,9 +376,9 @@ static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
|
||||
static int mcspi_wait_for_completion(struct omap2_mcspi *mcspi,
|
||||
struct completion *x)
|
||||
{
|
||||
if (spi_controller_is_slave(mcspi->master)) {
|
||||
if (spi_controller_is_target(mcspi->ctlr)) {
|
||||
if (wait_for_completion_interruptible(x) ||
|
||||
mcspi->slave_aborted)
|
||||
mcspi->target_aborted)
|
||||
return -EINTR;
|
||||
} else {
|
||||
wait_for_completion(x);
|
||||
@ -378,7 +390,7 @@ static int mcspi_wait_for_completion(struct omap2_mcspi *mcspi,
|
||||
static void omap2_mcspi_rx_callback(void *data)
|
||||
{
|
||||
struct spi_device *spi = data;
|
||||
struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master);
|
||||
struct omap2_mcspi *mcspi = spi_controller_get_devdata(spi->controller);
|
||||
struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi_get_chipselect(spi, 0)];
|
||||
|
||||
/* We must disable the DMA RX request */
|
||||
@ -390,7 +402,7 @@ static void omap2_mcspi_rx_callback(void *data)
|
||||
static void omap2_mcspi_tx_callback(void *data)
|
||||
{
|
||||
struct spi_device *spi = data;
|
||||
struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master);
|
||||
struct omap2_mcspi *mcspi = spi_controller_get_devdata(spi->controller);
|
||||
struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi_get_chipselect(spi, 0)];
|
||||
|
||||
/* We must disable the DMA TX request */
|
||||
@ -407,7 +419,7 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi,
|
||||
struct omap2_mcspi_dma *mcspi_dma;
|
||||
struct dma_async_tx_descriptor *tx;
|
||||
|
||||
mcspi = spi_master_get_devdata(spi->master);
|
||||
mcspi = spi_controller_get_devdata(spi->controller);
|
||||
mcspi_dma = &mcspi->dma_channels[spi_get_chipselect(spi, 0)];
|
||||
|
||||
dmaengine_slave_config(mcspi_dma->dma_tx, &cfg);
|
||||
@ -445,13 +457,13 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
|
||||
void __iomem *chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
|
||||
struct dma_async_tx_descriptor *tx;
|
||||
|
||||
mcspi = spi_master_get_devdata(spi->master);
|
||||
mcspi = spi_controller_get_devdata(spi->controller);
|
||||
mcspi_dma = &mcspi->dma_channels[spi_get_chipselect(spi, 0)];
|
||||
count = xfer->len;
|
||||
|
||||
/*
|
||||
* In the "End-of-Transfer Procedure" section for DMA RX in OMAP35x TRM
|
||||
* it mentions reducing DMA transfer length by one element in master
|
||||
* it mentions reducing DMA transfer length by one element in host
|
||||
* normal mode.
|
||||
*/
|
||||
if (mcspi->fifo_depth == 0)
|
||||
@ -514,7 +526,7 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
|
||||
omap2_mcspi_set_dma_req(spi, 1, 1);
|
||||
|
||||
ret = mcspi_wait_for_completion(mcspi, &mcspi_dma->dma_rx_completion);
|
||||
if (ret || mcspi->slave_aborted) {
|
||||
if (ret || mcspi->target_aborted) {
|
||||
dmaengine_terminate_sync(mcspi_dma->dma_rx);
|
||||
omap2_mcspi_set_dma_req(spi, 1, 0);
|
||||
return 0;
|
||||
@ -590,7 +602,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
void __iomem *irqstat_reg;
|
||||
int wait_res;
|
||||
|
||||
mcspi = spi_master_get_devdata(spi->master);
|
||||
mcspi = spi_controller_get_devdata(spi->controller);
|
||||
mcspi_dma = &mcspi->dma_channels[spi_get_chipselect(spi, 0)];
|
||||
|
||||
if (cs->word_len <= 8) {
|
||||
@ -617,14 +629,14 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
rx = xfer->rx_buf;
|
||||
tx = xfer->tx_buf;
|
||||
|
||||
mcspi->slave_aborted = false;
|
||||
mcspi->target_aborted = false;
|
||||
reinit_completion(&mcspi_dma->dma_tx_completion);
|
||||
reinit_completion(&mcspi_dma->dma_rx_completion);
|
||||
reinit_completion(&mcspi->txdone);
|
||||
if (tx) {
|
||||
/* Enable EOW IRQ to know end of tx in slave mode */
|
||||
if (spi_controller_is_slave(spi->master))
|
||||
mcspi_write_reg(spi->master,
|
||||
/* Enable EOW IRQ to know end of tx in target mode */
|
||||
if (spi_controller_is_target(spi->controller))
|
||||
mcspi_write_reg(spi->controller,
|
||||
OMAP2_MCSPI_IRQENABLE,
|
||||
OMAP2_MCSPI_IRQSTATUS_EOW);
|
||||
omap2_mcspi_tx_dma(spi, xfer, cfg);
|
||||
@ -637,15 +649,15 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
int ret;
|
||||
|
||||
ret = mcspi_wait_for_completion(mcspi, &mcspi_dma->dma_tx_completion);
|
||||
if (ret || mcspi->slave_aborted) {
|
||||
if (ret || mcspi->target_aborted) {
|
||||
dmaengine_terminate_sync(mcspi_dma->dma_tx);
|
||||
omap2_mcspi_set_dma_req(spi, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (spi_controller_is_slave(mcspi->master)) {
|
||||
if (spi_controller_is_target(mcspi->ctlr)) {
|
||||
ret = mcspi_wait_for_completion(mcspi, &mcspi->txdone);
|
||||
if (ret || mcspi->slave_aborted)
|
||||
if (ret || mcspi->target_aborted)
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -656,7 +668,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
OMAP2_MCSPI_IRQSTATUS_EOW) < 0)
|
||||
dev_err(&spi->dev, "EOW timed out\n");
|
||||
|
||||
mcspi_write_reg(mcspi->master, OMAP2_MCSPI_IRQSTATUS,
|
||||
mcspi_write_reg(mcspi->ctlr, OMAP2_MCSPI_IRQSTATUS,
|
||||
OMAP2_MCSPI_IRQSTATUS_EOW);
|
||||
}
|
||||
|
||||
@ -880,12 +892,119 @@ out:
|
||||
return count - c;
|
||||
}
|
||||
|
||||
static u32 omap2_mcspi_calc_divisor(u32 speed_hz)
|
||||
static unsigned
|
||||
omap2_mcspi_txrx_piofifo(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
{
|
||||
struct omap2_mcspi_cs *cs = spi->controller_state;
|
||||
struct omap2_mcspi *mcspi;
|
||||
unsigned int count, c;
|
||||
unsigned int iter, cwc;
|
||||
int last_request;
|
||||
void __iomem *base = cs->base;
|
||||
void __iomem *tx_reg;
|
||||
void __iomem *rx_reg;
|
||||
void __iomem *chstat_reg;
|
||||
void __iomem *irqstat_reg;
|
||||
int word_len, bytes_per_word;
|
||||
u8 *rx;
|
||||
const u8 *tx;
|
||||
|
||||
mcspi = spi_controller_get_devdata(spi->controller);
|
||||
count = xfer->len;
|
||||
c = count;
|
||||
word_len = cs->word_len;
|
||||
bytes_per_word = mcspi_bytes_per_word(word_len);
|
||||
|
||||
/*
|
||||
* We store the pre-calculated register addresses on stack to speed
|
||||
* up the transfer loop.
|
||||
*/
|
||||
tx_reg = base + OMAP2_MCSPI_TX0;
|
||||
rx_reg = base + OMAP2_MCSPI_RX0;
|
||||
chstat_reg = base + OMAP2_MCSPI_CHSTAT0;
|
||||
irqstat_reg = base + OMAP2_MCSPI_IRQSTATUS;
|
||||
|
||||
if (c < (word_len >> 3))
|
||||
return 0;
|
||||
|
||||
rx = xfer->rx_buf;
|
||||
tx = xfer->tx_buf;
|
||||
|
||||
do {
|
||||
/* calculate number of words in current iteration */
|
||||
cwc = min((unsigned int)mcspi->fifo_depth / bytes_per_word,
|
||||
c / bytes_per_word);
|
||||
last_request = cwc != (mcspi->fifo_depth / bytes_per_word);
|
||||
if (tx) {
|
||||
if (mcspi_wait_for_reg_bit(irqstat_reg,
|
||||
OMAP2_MCSPI_IRQSTATUS_TX0_EMPTY) < 0) {
|
||||
dev_err(&spi->dev, "TX Empty timed out\n");
|
||||
goto out;
|
||||
}
|
||||
writel_relaxed(OMAP2_MCSPI_IRQSTATUS_TX0_EMPTY, irqstat_reg);
|
||||
|
||||
for (iter = 0; iter < cwc; iter++, tx += bytes_per_word) {
|
||||
if (bytes_per_word == 1)
|
||||
writel_relaxed(*tx, tx_reg);
|
||||
else if (bytes_per_word == 2)
|
||||
writel_relaxed(*((u16 *)tx), tx_reg);
|
||||
else if (bytes_per_word == 4)
|
||||
writel_relaxed(*((u32 *)tx), tx_reg);
|
||||
}
|
||||
}
|
||||
|
||||
if (rx) {
|
||||
if (!last_request &&
|
||||
mcspi_wait_for_reg_bit(irqstat_reg,
|
||||
OMAP2_MCSPI_IRQSTATUS_RX0_FULL) < 0) {
|
||||
dev_err(&spi->dev, "RX_FULL timed out\n");
|
||||
goto out;
|
||||
}
|
||||
writel_relaxed(OMAP2_MCSPI_IRQSTATUS_RX0_FULL, irqstat_reg);
|
||||
|
||||
for (iter = 0; iter < cwc; iter++, rx += bytes_per_word) {
|
||||
if (last_request &&
|
||||
mcspi_wait_for_reg_bit(chstat_reg,
|
||||
OMAP2_MCSPI_CHSTAT_RXS) < 0) {
|
||||
dev_err(&spi->dev, "RXS timed out\n");
|
||||
goto out;
|
||||
}
|
||||
if (bytes_per_word == 1)
|
||||
*rx = readl_relaxed(rx_reg);
|
||||
else if (bytes_per_word == 2)
|
||||
*((u16 *)rx) = readl_relaxed(rx_reg);
|
||||
else if (bytes_per_word == 4)
|
||||
*((u32 *)rx) = readl_relaxed(rx_reg);
|
||||
}
|
||||
}
|
||||
|
||||
if (last_request) {
|
||||
if (mcspi_wait_for_reg_bit(chstat_reg,
|
||||
OMAP2_MCSPI_CHSTAT_EOT) < 0) {
|
||||
dev_err(&spi->dev, "EOT timed out\n");
|
||||
goto out;
|
||||
}
|
||||
if (mcspi_wait_for_reg_bit(chstat_reg,
|
||||
OMAP2_MCSPI_CHSTAT_TXFFE) < 0) {
|
||||
dev_err(&spi->dev, "TXFFE timed out\n");
|
||||
goto out;
|
||||
}
|
||||
omap2_mcspi_set_enable(spi, 0);
|
||||
}
|
||||
c -= cwc * bytes_per_word;
|
||||
} while (c >= bytes_per_word);
|
||||
|
||||
out:
|
||||
omap2_mcspi_set_enable(spi, 1);
|
||||
return count - c;
|
||||
}
|
||||
|
||||
static u32 omap2_mcspi_calc_divisor(u32 speed_hz, u32 ref_clk_hz)
|
||||
{
|
||||
u32 div;
|
||||
|
||||
for (div = 0; div < 15; div++)
|
||||
if (speed_hz >= (OMAP2_MCSPI_MAX_FREQ >> div))
|
||||
if (speed_hz >= (ref_clk_hz >> div))
|
||||
return div;
|
||||
|
||||
return 15;
|
||||
@ -897,11 +1016,11 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
|
||||
{
|
||||
struct omap2_mcspi_cs *cs = spi->controller_state;
|
||||
struct omap2_mcspi *mcspi;
|
||||
u32 l = 0, clkd = 0, div, extclk = 0, clkg = 0;
|
||||
u32 ref_clk_hz, l = 0, clkd = 0, div, extclk = 0, clkg = 0;
|
||||
u8 word_len = spi->bits_per_word;
|
||||
u32 speed_hz = spi->max_speed_hz;
|
||||
|
||||
mcspi = spi_master_get_devdata(spi->master);
|
||||
mcspi = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
if (t != NULL && t->bits_per_word)
|
||||
word_len = t->bits_per_word;
|
||||
@ -911,14 +1030,15 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
|
||||
if (t && t->speed_hz)
|
||||
speed_hz = t->speed_hz;
|
||||
|
||||
speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ);
|
||||
if (speed_hz < (OMAP2_MCSPI_MAX_FREQ / OMAP2_MCSPI_MAX_DIVIDER)) {
|
||||
clkd = omap2_mcspi_calc_divisor(speed_hz);
|
||||
speed_hz = OMAP2_MCSPI_MAX_FREQ >> clkd;
|
||||
ref_clk_hz = mcspi->ref_clk_hz;
|
||||
speed_hz = min_t(u32, speed_hz, ref_clk_hz);
|
||||
if (speed_hz < (ref_clk_hz / OMAP2_MCSPI_MAX_DIVIDER)) {
|
||||
clkd = omap2_mcspi_calc_divisor(speed_hz, ref_clk_hz);
|
||||
speed_hz = ref_clk_hz >> clkd;
|
||||
clkg = 0;
|
||||
} else {
|
||||
div = (OMAP2_MCSPI_MAX_FREQ + speed_hz - 1) / speed_hz;
|
||||
speed_hz = OMAP2_MCSPI_MAX_FREQ / div;
|
||||
div = (ref_clk_hz + speed_hz - 1) / speed_hz;
|
||||
speed_hz = ref_clk_hz / div;
|
||||
clkd = (div - 1) & 0xf;
|
||||
extclk = (div - 1) >> 4;
|
||||
clkg = OMAP2_MCSPI_CHCONF_CLKG;
|
||||
@ -926,7 +1046,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
|
||||
|
||||
l = mcspi_cached_chconf0(spi);
|
||||
|
||||
/* standard 4-wire master mode: SCK, MOSI/out, MISO/in, nCS
|
||||
/* standard 4-wire host mode: SCK, MOSI/out, MISO/in, nCS
|
||||
* REVISIT: this controller could support SPI_3WIRE mode.
|
||||
*/
|
||||
if (mcspi->pin_dir == MCSPI_PINDIR_D0_IN_D1_OUT) {
|
||||
@ -1017,13 +1137,13 @@ no_dma:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void omap2_mcspi_release_dma(struct spi_master *master)
|
||||
static void omap2_mcspi_release_dma(struct spi_controller *ctlr)
|
||||
{
|
||||
struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
|
||||
struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr);
|
||||
struct omap2_mcspi_dma *mcspi_dma;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < master->num_chipselect; i++) {
|
||||
for (i = 0; i < ctlr->num_chipselect; i++) {
|
||||
mcspi_dma = &mcspi->dma_channels[i];
|
||||
|
||||
if (mcspi_dma->dma_rx) {
|
||||
@ -1054,7 +1174,7 @@ static int omap2_mcspi_setup(struct spi_device *spi)
|
||||
{
|
||||
bool initial_setup = false;
|
||||
int ret;
|
||||
struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master);
|
||||
struct omap2_mcspi *mcspi = spi_controller_get_devdata(spi->controller);
|
||||
struct omap2_mcspi_regs *ctx = &mcspi->ctx;
|
||||
struct omap2_mcspi_cs *cs = spi->controller_state;
|
||||
|
||||
@ -1096,24 +1216,24 @@ static irqreturn_t omap2_mcspi_irq_handler(int irq, void *data)
|
||||
struct omap2_mcspi *mcspi = data;
|
||||
u32 irqstat;
|
||||
|
||||
irqstat = mcspi_read_reg(mcspi->master, OMAP2_MCSPI_IRQSTATUS);
|
||||
irqstat = mcspi_read_reg(mcspi->ctlr, OMAP2_MCSPI_IRQSTATUS);
|
||||
if (!irqstat)
|
||||
return IRQ_NONE;
|
||||
|
||||
/* Disable IRQ and wakeup slave xfer task */
|
||||
mcspi_write_reg(mcspi->master, OMAP2_MCSPI_IRQENABLE, 0);
|
||||
/* Disable IRQ and wakeup target xfer task */
|
||||
mcspi_write_reg(mcspi->ctlr, OMAP2_MCSPI_IRQENABLE, 0);
|
||||
if (irqstat & OMAP2_MCSPI_IRQSTATUS_EOW)
|
||||
complete(&mcspi->txdone);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int omap2_mcspi_slave_abort(struct spi_master *master)
|
||||
static int omap2_mcspi_target_abort(struct spi_controller *ctlr)
|
||||
{
|
||||
struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
|
||||
struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr);
|
||||
struct omap2_mcspi_dma *mcspi_dma = mcspi->dma_channels;
|
||||
|
||||
mcspi->slave_aborted = true;
|
||||
mcspi->target_aborted = true;
|
||||
complete(&mcspi_dma->dma_rx_completion);
|
||||
complete(&mcspi_dma->dma_tx_completion);
|
||||
complete(&mcspi->txdone);
|
||||
@ -1121,7 +1241,7 @@ static int omap2_mcspi_slave_abort(struct spi_master *master)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int omap2_mcspi_transfer_one(struct spi_master *master,
|
||||
static int omap2_mcspi_transfer_one(struct spi_controller *ctlr,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *t)
|
||||
{
|
||||
@ -1129,7 +1249,7 @@ static int omap2_mcspi_transfer_one(struct spi_master *master,
|
||||
/* We only enable one channel at a time -- the one whose message is
|
||||
* -- although this controller would gladly
|
||||
* arbitrate among multiple channels. This corresponds to "single
|
||||
* channel" master mode. As a side effect, we need to manage the
|
||||
* channel" host mode. As a side effect, we need to manage the
|
||||
* chipselect with the FORCE bit ... CS != channel enable.
|
||||
*/
|
||||
|
||||
@ -1141,13 +1261,13 @@ static int omap2_mcspi_transfer_one(struct spi_master *master,
|
||||
int status = 0;
|
||||
u32 chconf;
|
||||
|
||||
mcspi = spi_master_get_devdata(master);
|
||||
mcspi = spi_controller_get_devdata(ctlr);
|
||||
mcspi_dma = mcspi->dma_channels + spi_get_chipselect(spi, 0);
|
||||
cs = spi->controller_state;
|
||||
cd = spi->controller_data;
|
||||
|
||||
/*
|
||||
* The slave driver could have changed spi->mode in which case
|
||||
* The target driver could have changed spi->mode in which case
|
||||
* it will be different from cs->mode (the current hardware setup).
|
||||
* If so, set par_override (even though its not a parity issue) so
|
||||
* omap2_mcspi_setup_transfer will be called to configure the hardware
|
||||
@ -1175,7 +1295,7 @@ static int omap2_mcspi_transfer_one(struct spi_master *master,
|
||||
if (cd && cd->cs_per_word) {
|
||||
chconf = mcspi->ctx.modulctrl;
|
||||
chconf &= ~OMAP2_MCSPI_MODULCTRL_SINGLE;
|
||||
mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, chconf);
|
||||
mcspi_write_reg(ctlr, OMAP2_MCSPI_MODULCTRL, chconf);
|
||||
mcspi->ctx.modulctrl =
|
||||
mcspi_read_cs_reg(spi, OMAP2_MCSPI_MODULCTRL);
|
||||
}
|
||||
@ -1201,9 +1321,11 @@ static int omap2_mcspi_transfer_one(struct spi_master *master,
|
||||
unsigned count;
|
||||
|
||||
if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
|
||||
master->cur_msg_mapped &&
|
||||
master->can_dma(master, spi, t))
|
||||
omap2_mcspi_set_fifo(spi, t, 1);
|
||||
ctlr->cur_msg_mapped &&
|
||||
ctlr->can_dma(ctlr, spi, t))
|
||||
omap2_mcspi_set_fifo(spi, t, 1, 1);
|
||||
else if (t->len > OMAP2_MCSPI_MAX_FIFODEPTH)
|
||||
omap2_mcspi_set_fifo(spi, t, 1, 0);
|
||||
|
||||
omap2_mcspi_set_enable(spi, 1);
|
||||
|
||||
@ -1213,9 +1335,11 @@ static int omap2_mcspi_transfer_one(struct spi_master *master,
|
||||
+ OMAP2_MCSPI_TX0);
|
||||
|
||||
if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
|
||||
master->cur_msg_mapped &&
|
||||
master->can_dma(master, spi, t))
|
||||
ctlr->cur_msg_mapped &&
|
||||
ctlr->can_dma(ctlr, spi, t))
|
||||
count = omap2_mcspi_txrx_dma(spi, t);
|
||||
else if (mcspi->fifo_depth > 0)
|
||||
count = omap2_mcspi_txrx_piofifo(spi, t);
|
||||
else
|
||||
count = omap2_mcspi_txrx_pio(spi, t);
|
||||
|
||||
@ -1228,7 +1352,7 @@ static int omap2_mcspi_transfer_one(struct spi_master *master,
|
||||
omap2_mcspi_set_enable(spi, 0);
|
||||
|
||||
if (mcspi->fifo_depth > 0)
|
||||
omap2_mcspi_set_fifo(spi, t, 0);
|
||||
omap2_mcspi_set_fifo(spi, t, 0, 0);
|
||||
|
||||
out:
|
||||
/* Restore defaults if they were overriden */
|
||||
@ -1240,7 +1364,7 @@ out:
|
||||
if (cd && cd->cs_per_word) {
|
||||
chconf = mcspi->ctx.modulctrl;
|
||||
chconf |= OMAP2_MCSPI_MODULCTRL_SINGLE;
|
||||
mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, chconf);
|
||||
mcspi_write_reg(ctlr, OMAP2_MCSPI_MODULCTRL, chconf);
|
||||
mcspi->ctx.modulctrl =
|
||||
mcspi_read_cs_reg(spi, OMAP2_MCSPI_MODULCTRL);
|
||||
}
|
||||
@ -1251,15 +1375,15 @@ out:
|
||||
omap2_mcspi_set_cs(spi, !(spi->mode & SPI_CS_HIGH));
|
||||
|
||||
if (mcspi->fifo_depth > 0 && t)
|
||||
omap2_mcspi_set_fifo(spi, t, 0);
|
||||
omap2_mcspi_set_fifo(spi, t, 0, 0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int omap2_mcspi_prepare_message(struct spi_master *master,
|
||||
static int omap2_mcspi_prepare_message(struct spi_controller *ctlr,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
|
||||
struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr);
|
||||
struct omap2_mcspi_regs *ctx = &mcspi->ctx;
|
||||
struct omap2_mcspi_cs *cs;
|
||||
|
||||
@ -1283,29 +1407,29 @@ static int omap2_mcspi_prepare_message(struct spi_master *master,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool omap2_mcspi_can_dma(struct spi_master *master,
|
||||
static bool omap2_mcspi_can_dma(struct spi_controller *ctlr,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master);
|
||||
struct omap2_mcspi *mcspi = spi_controller_get_devdata(spi->controller);
|
||||
struct omap2_mcspi_dma *mcspi_dma =
|
||||
&mcspi->dma_channels[spi_get_chipselect(spi, 0)];
|
||||
|
||||
if (!mcspi_dma->dma_rx || !mcspi_dma->dma_tx)
|
||||
return false;
|
||||
|
||||
if (spi_controller_is_slave(master))
|
||||
if (spi_controller_is_target(ctlr))
|
||||
return true;
|
||||
|
||||
master->dma_rx = mcspi_dma->dma_rx;
|
||||
master->dma_tx = mcspi_dma->dma_tx;
|
||||
ctlr->dma_rx = mcspi_dma->dma_rx;
|
||||
ctlr->dma_tx = mcspi_dma->dma_tx;
|
||||
|
||||
return (xfer->len >= DMA_MIN_BYTES);
|
||||
}
|
||||
|
||||
static size_t omap2_mcspi_max_xfer_size(struct spi_device *spi)
|
||||
{
|
||||
struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master);
|
||||
struct omap2_mcspi *mcspi = spi_controller_get_devdata(spi->controller);
|
||||
struct omap2_mcspi_dma *mcspi_dma =
|
||||
&mcspi->dma_channels[spi_get_chipselect(spi, 0)];
|
||||
|
||||
@ -1317,7 +1441,7 @@ static size_t omap2_mcspi_max_xfer_size(struct spi_device *spi)
|
||||
|
||||
static int omap2_mcspi_controller_setup(struct omap2_mcspi *mcspi)
|
||||
{
|
||||
struct spi_master *master = mcspi->master;
|
||||
struct spi_controller *ctlr = mcspi->ctlr;
|
||||
struct omap2_mcspi_regs *ctx = &mcspi->ctx;
|
||||
int ret = 0;
|
||||
|
||||
@ -1325,11 +1449,11 @@ static int omap2_mcspi_controller_setup(struct omap2_mcspi *mcspi)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE,
|
||||
mcspi_write_reg(ctlr, OMAP2_MCSPI_WAKEUPENABLE,
|
||||
OMAP2_MCSPI_WAKEUPENABLE_WKEN);
|
||||
ctx->wakeupenable = OMAP2_MCSPI_WAKEUPENABLE_WKEN;
|
||||
|
||||
omap2_mcspi_set_mode(master);
|
||||
omap2_mcspi_set_mode(ctlr);
|
||||
pm_runtime_mark_last_busy(mcspi->dev);
|
||||
pm_runtime_put_autosuspend(mcspi->dev);
|
||||
return 0;
|
||||
@ -1353,8 +1477,8 @@ static int omap_mcspi_runtime_suspend(struct device *dev)
|
||||
*/
|
||||
static int omap_mcspi_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
|
||||
struct spi_controller *ctlr = dev_get_drvdata(dev);
|
||||
struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr);
|
||||
struct omap2_mcspi_regs *ctx = &mcspi->ctx;
|
||||
struct omap2_mcspi_cs *cs;
|
||||
int error;
|
||||
@ -1364,8 +1488,8 @@ static int omap_mcspi_runtime_resume(struct device *dev)
|
||||
dev_warn(dev, "%s: failed to set pins: %i\n", __func__, error);
|
||||
|
||||
/* McSPI: context restore */
|
||||
mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, ctx->modulctrl);
|
||||
mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, ctx->wakeupenable);
|
||||
mcspi_write_reg(ctlr, OMAP2_MCSPI_MODULCTRL, ctx->modulctrl);
|
||||
mcspi_write_reg(ctlr, OMAP2_MCSPI_WAKEUPENABLE, ctx->wakeupenable);
|
||||
|
||||
list_for_each_entry(cs, &ctx->cs, node) {
|
||||
/*
|
||||
@ -1420,7 +1544,7 @@ MODULE_DEVICE_TABLE(of, omap_mcspi_of_match);
|
||||
|
||||
static int omap2_mcspi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct spi_controller *ctlr;
|
||||
const struct omap2_mcspi_platform_config *pdata;
|
||||
struct omap2_mcspi *mcspi;
|
||||
struct resource *r;
|
||||
@ -1430,32 +1554,30 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
|
||||
const struct of_device_id *match;
|
||||
|
||||
if (of_property_read_bool(node, "spi-slave"))
|
||||
master = spi_alloc_slave(&pdev->dev, sizeof(*mcspi));
|
||||
ctlr = spi_alloc_target(&pdev->dev, sizeof(*mcspi));
|
||||
else
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(*mcspi));
|
||||
if (!master)
|
||||
ctlr = spi_alloc_host(&pdev->dev, sizeof(*mcspi));
|
||||
if (!ctlr)
|
||||
return -ENOMEM;
|
||||
|
||||
/* the spi->mode bits understood by this driver: */
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
|
||||
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
|
||||
master->setup = omap2_mcspi_setup;
|
||||
master->auto_runtime_pm = true;
|
||||
master->prepare_message = omap2_mcspi_prepare_message;
|
||||
master->can_dma = omap2_mcspi_can_dma;
|
||||
master->transfer_one = omap2_mcspi_transfer_one;
|
||||
master->set_cs = omap2_mcspi_set_cs;
|
||||
master->cleanup = omap2_mcspi_cleanup;
|
||||
master->slave_abort = omap2_mcspi_slave_abort;
|
||||
master->dev.of_node = node;
|
||||
master->max_speed_hz = OMAP2_MCSPI_MAX_FREQ;
|
||||
master->min_speed_hz = OMAP2_MCSPI_MAX_FREQ >> 15;
|
||||
master->use_gpio_descriptors = true;
|
||||
ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
|
||||
ctlr->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
|
||||
ctlr->setup = omap2_mcspi_setup;
|
||||
ctlr->auto_runtime_pm = true;
|
||||
ctlr->prepare_message = omap2_mcspi_prepare_message;
|
||||
ctlr->can_dma = omap2_mcspi_can_dma;
|
||||
ctlr->transfer_one = omap2_mcspi_transfer_one;
|
||||
ctlr->set_cs = omap2_mcspi_set_cs;
|
||||
ctlr->cleanup = omap2_mcspi_cleanup;
|
||||
ctlr->target_abort = omap2_mcspi_target_abort;
|
||||
ctlr->dev.of_node = node;
|
||||
ctlr->use_gpio_descriptors = true;
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
platform_set_drvdata(pdev, ctlr);
|
||||
|
||||
mcspi = spi_master_get_devdata(master);
|
||||
mcspi->master = master;
|
||||
mcspi = spi_controller_get_devdata(ctlr);
|
||||
mcspi->ctlr = ctlr;
|
||||
|
||||
match = of_match_device(omap_mcspi_of_match, &pdev->dev);
|
||||
if (match) {
|
||||
@ -1463,24 +1585,24 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
|
||||
pdata = match->data;
|
||||
|
||||
of_property_read_u32(node, "ti,spi-num-cs", &num_cs);
|
||||
master->num_chipselect = num_cs;
|
||||
ctlr->num_chipselect = num_cs;
|
||||
if (of_property_read_bool(node, "ti,pindir-d0-out-d1-in"))
|
||||
mcspi->pin_dir = MCSPI_PINDIR_D0_OUT_D1_IN;
|
||||
} else {
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
master->num_chipselect = pdata->num_cs;
|
||||
ctlr->num_chipselect = pdata->num_cs;
|
||||
mcspi->pin_dir = pdata->pin_dir;
|
||||
}
|
||||
regs_offset = pdata->regs_offset;
|
||||
if (pdata->max_xfer_len) {
|
||||
mcspi->max_xfer_len = pdata->max_xfer_len;
|
||||
master->max_transfer_size = omap2_mcspi_max_xfer_size;
|
||||
ctlr->max_transfer_size = omap2_mcspi_max_xfer_size;
|
||||
}
|
||||
|
||||
mcspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r);
|
||||
if (IS_ERR(mcspi->base)) {
|
||||
status = PTR_ERR(mcspi->base);
|
||||
goto free_master;
|
||||
goto free_ctlr;
|
||||
}
|
||||
mcspi->phys = r->start + regs_offset;
|
||||
mcspi->base += regs_offset;
|
||||
@ -1489,36 +1611,44 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
|
||||
|
||||
INIT_LIST_HEAD(&mcspi->ctx.cs);
|
||||
|
||||
mcspi->dma_channels = devm_kcalloc(&pdev->dev, master->num_chipselect,
|
||||
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_master;
|
||||
goto free_ctlr;
|
||||
}
|
||||
|
||||
for (i = 0; i < master->num_chipselect; i++) {
|
||||
for (i = 0; i < ctlr->num_chipselect; i++) {
|
||||
sprintf(mcspi->dma_channels[i].dma_rx_ch_name, "rx%d", i);
|
||||
sprintf(mcspi->dma_channels[i].dma_tx_ch_name, "tx%d", i);
|
||||
|
||||
status = omap2_mcspi_request_dma(mcspi,
|
||||
&mcspi->dma_channels[i]);
|
||||
if (status == -EPROBE_DEFER)
|
||||
goto free_master;
|
||||
goto free_ctlr;
|
||||
}
|
||||
|
||||
status = platform_get_irq(pdev, 0);
|
||||
if (status < 0)
|
||||
goto free_master;
|
||||
goto free_ctlr;
|
||||
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_master;
|
||||
goto free_ctlr;
|
||||
}
|
||||
|
||||
mcspi->ref_clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);
|
||||
if (mcspi->ref_clk)
|
||||
mcspi->ref_clk_hz = clk_get_rate(mcspi->ref_clk);
|
||||
else
|
||||
mcspi->ref_clk_hz = OMAP2_MCSPI_MAX_FREQ;
|
||||
ctlr->max_speed_hz = mcspi->ref_clk_hz;
|
||||
ctlr->min_speed_hz = mcspi->ref_clk_hz >> 15;
|
||||
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
@ -1527,7 +1657,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
|
||||
if (status < 0)
|
||||
goto disable_pm;
|
||||
|
||||
status = devm_spi_register_controller(&pdev->dev, master);
|
||||
status = devm_spi_register_controller(&pdev->dev, ctlr);
|
||||
if (status < 0)
|
||||
goto disable_pm;
|
||||
|
||||
@ -1537,18 +1667,18 @@ disable_pm:
|
||||
pm_runtime_dont_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_put_sync(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
free_master:
|
||||
omap2_mcspi_release_dma(master);
|
||||
spi_master_put(master);
|
||||
free_ctlr:
|
||||
omap2_mcspi_release_dma(ctlr);
|
||||
spi_controller_put(ctlr);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void omap2_mcspi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master = platform_get_drvdata(pdev);
|
||||
struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
|
||||
struct spi_controller *ctlr = platform_get_drvdata(pdev);
|
||||
struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr);
|
||||
|
||||
omap2_mcspi_release_dma(master);
|
||||
omap2_mcspi_release_dma(ctlr);
|
||||
|
||||
pm_runtime_dont_use_autosuspend(mcspi->dev);
|
||||
pm_runtime_put_sync(mcspi->dev);
|
||||
@ -1560,8 +1690,8 @@ MODULE_ALIAS("platform:omap2_mcspi");
|
||||
|
||||
static int __maybe_unused omap2_mcspi_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
|
||||
struct spi_controller *ctlr = dev_get_drvdata(dev);
|
||||
struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr);
|
||||
int error;
|
||||
|
||||
error = pinctrl_pm_select_sleep_state(dev);
|
||||
@ -1569,9 +1699,9 @@ static int __maybe_unused omap2_mcspi_suspend(struct device *dev)
|
||||
dev_warn(mcspi->dev, "%s: failed to set pins: %i\n",
|
||||
__func__, error);
|
||||
|
||||
error = spi_master_suspend(master);
|
||||
error = spi_controller_suspend(ctlr);
|
||||
if (error)
|
||||
dev_warn(mcspi->dev, "%s: master suspend failed: %i\n",
|
||||
dev_warn(mcspi->dev, "%s: controller suspend failed: %i\n",
|
||||
__func__, error);
|
||||
|
||||
return pm_runtime_force_suspend(dev);
|
||||
@ -1579,13 +1709,13 @@ static int __maybe_unused omap2_mcspi_suspend(struct device *dev)
|
||||
|
||||
static int __maybe_unused omap2_mcspi_resume(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
|
||||
struct spi_controller *ctlr = dev_get_drvdata(dev);
|
||||
struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr);
|
||||
int error;
|
||||
|
||||
error = spi_master_resume(master);
|
||||
error = spi_controller_resume(ctlr);
|
||||
if (error)
|
||||
dev_warn(mcspi->dev, "%s: master resume failed: %i\n",
|
||||
dev_warn(mcspi->dev, "%s: controller resume failed: %i\n",
|
||||
__func__, error);
|
||||
|
||||
return pm_runtime_force_resume(dev);
|
||||
|
@ -688,21 +688,17 @@ static int orion_spi_probe(struct platform_device *pdev)
|
||||
devdata = devdata ? devdata : &orion_spi_dev_data;
|
||||
spi->devdata = devdata;
|
||||
|
||||
spi->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
spi->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(spi->clk)) {
|
||||
status = PTR_ERR(spi->clk);
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = clk_prepare_enable(spi->clk);
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
/* 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_rel_clk;
|
||||
goto out;
|
||||
}
|
||||
if (!IS_ERR(spi->axi_clk))
|
||||
clk_prepare_enable(spi->axi_clk);
|
||||
@ -795,8 +791,6 @@ out_rel_pm:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
out_rel_axi_clk:
|
||||
clk_disable_unprepare(spi->axi_clk);
|
||||
out_rel_clk:
|
||||
clk_disable_unprepare(spi->clk);
|
||||
out:
|
||||
spi_controller_put(host);
|
||||
return status;
|
||||
@ -810,7 +804,6 @@ static void orion_spi_remove(struct platform_device *pdev)
|
||||
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
clk_disable_unprepare(spi->axi_clk);
|
||||
clk_disable_unprepare(spi->clk);
|
||||
|
||||
spi_unregister_controller(host);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
@ -77,7 +77,7 @@ struct pci1xxxx_spi {
|
||||
struct pci_dev *dev;
|
||||
u8 total_hw_instances;
|
||||
void __iomem *reg_base;
|
||||
struct pci1xxxx_spi_internal *spi_int[];
|
||||
struct pci1xxxx_spi_internal *spi_int[] __counted_by(total_hw_instances);
|
||||
};
|
||||
|
||||
static const struct pci_device_id pci1xxxx_spi_pci_id_table[] = {
|
||||
|
@ -593,33 +593,20 @@ static int pic32_sqi_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
/* clocks */
|
||||
sqi->sys_clk = devm_clk_get(&pdev->dev, "reg_ck");
|
||||
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;
|
||||
}
|
||||
|
||||
sqi->base_clk = devm_clk_get(&pdev->dev, "spi_ck");
|
||||
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;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(sqi->sys_clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "sys clk enable failed\n");
|
||||
goto err_free_host;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(sqi->base_clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "base clk enable failed\n");
|
||||
clk_disable_unprepare(sqi->sys_clk);
|
||||
goto err_free_host;
|
||||
}
|
||||
|
||||
init_completion(&sqi->xfer_done);
|
||||
|
||||
/* initialize hardware */
|
||||
@ -629,7 +616,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_disable_clk;
|
||||
goto err_free_host;
|
||||
}
|
||||
|
||||
/* install irq handlers */
|
||||
@ -669,10 +656,6 @@ static int pic32_sqi_probe(struct platform_device *pdev)
|
||||
err_free_ring:
|
||||
ring_desc_ring_free(sqi);
|
||||
|
||||
err_disable_clk:
|
||||
clk_disable_unprepare(sqi->base_clk);
|
||||
clk_disable_unprepare(sqi->sys_clk);
|
||||
|
||||
err_free_host:
|
||||
spi_controller_put(host);
|
||||
return ret;
|
||||
@ -685,10 +668,6 @@ static void pic32_sqi_remove(struct platform_device *pdev)
|
||||
/* release resources */
|
||||
free_irq(sqi->irq, sqi);
|
||||
ring_desc_ring_free(sqi);
|
||||
|
||||
/* disable clk */
|
||||
clk_disable_unprepare(sqi->base_clk);
|
||||
clk_disable_unprepare(sqi->sys_clk);
|
||||
}
|
||||
|
||||
static const struct of_device_id pic32_sqi_of_ids[] = {
|
||||
|
@ -730,17 +730,13 @@ static int pic32_spi_hw_probe(struct platform_device *pdev,
|
||||
return pic32s->tx_irq;
|
||||
|
||||
/* get clock */
|
||||
pic32s->clk = devm_clk_get(&pdev->dev, "mck0");
|
||||
pic32s->clk = devm_clk_get_enabled(&pdev->dev, "mck0");
|
||||
if (IS_ERR(pic32s->clk)) {
|
||||
dev_err(&pdev->dev, "clk not found\n");
|
||||
ret = PTR_ERR(pic32s->clk);
|
||||
goto err_unmap_mem;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(pic32s->clk);
|
||||
if (ret)
|
||||
goto err_unmap_mem;
|
||||
|
||||
pic32_spi_hw_init(pic32s);
|
||||
|
||||
return 0;
|
||||
@ -837,7 +833,6 @@ static int pic32_spi_probe(struct platform_device *pdev)
|
||||
|
||||
err_bailout:
|
||||
pic32_spi_dma_unprep(pic32s);
|
||||
clk_disable_unprepare(pic32s->clk);
|
||||
err_host:
|
||||
spi_controller_put(host);
|
||||
return ret;
|
||||
@ -849,7 +844,6 @@ static void pic32_spi_remove(struct platform_device *pdev)
|
||||
|
||||
pic32s = platform_get_drvdata(pdev);
|
||||
pic32_spi_disable(pic32s);
|
||||
clk_disable_unprepare(pic32s->clk);
|
||||
pic32_spi_dma_unprep(pic32s);
|
||||
}
|
||||
|
||||
|
@ -2168,19 +2168,13 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
dev_info(&adev->dev, "mapped registers from %pa to %p\n",
|
||||
&adev->res.start, pl022->virtbase);
|
||||
|
||||
pl022->clk = devm_clk_get(&adev->dev, NULL);
|
||||
pl022->clk = devm_clk_get_enabled(&adev->dev, NULL);
|
||||
if (IS_ERR(pl022->clk)) {
|
||||
status = PTR_ERR(pl022->clk);
|
||||
dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n");
|
||||
goto err_no_clk;
|
||||
}
|
||||
|
||||
status = clk_prepare_enable(pl022->clk);
|
||||
if (status) {
|
||||
dev_err(&adev->dev, "could not enable SSP/SPI bus clock\n");
|
||||
goto err_no_clk_en;
|
||||
}
|
||||
|
||||
/* Initialize transfer pump */
|
||||
tasklet_init(&pl022->pump_transfers, pump_transfers,
|
||||
(unsigned long)pl022);
|
||||
@ -2240,8 +2234,6 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
if (platform_info->enable_dma)
|
||||
pl022_dma_remove(pl022);
|
||||
err_no_irq:
|
||||
clk_disable_unprepare(pl022->clk);
|
||||
err_no_clk_en:
|
||||
err_no_clk:
|
||||
err_no_ioremap:
|
||||
amba_release_regions(adev);
|
||||
@ -2268,7 +2260,6 @@ pl022_remove(struct amba_device *adev)
|
||||
if (pl022->host_info->enable_dma)
|
||||
pl022_dma_remove(pl022);
|
||||
|
||||
clk_disable_unprepare(pl022->clk);
|
||||
amba_release_regions(adev);
|
||||
tasklet_disable(&pl022->pump_transfers);
|
||||
}
|
||||
|
@ -6,12 +6,14 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/interconnect.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_opp.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/dmaengine.h>
|
||||
@ -121,11 +123,14 @@
|
||||
#define SPI_DELAY_THRESHOLD 1
|
||||
#define SPI_DELAY_RETRY 10
|
||||
|
||||
#define SPI_BUS_WIDTH 8
|
||||
|
||||
struct spi_qup {
|
||||
void __iomem *base;
|
||||
struct device *dev;
|
||||
struct clk *cclk; /* core clock */
|
||||
struct clk *iclk; /* interface clock */
|
||||
struct icc_path *icc_path; /* interconnect to RAM */
|
||||
int irq;
|
||||
spinlock_t lock;
|
||||
|
||||
@ -148,6 +153,8 @@ struct spi_qup {
|
||||
int mode;
|
||||
struct dma_slave_config rx_conf;
|
||||
struct dma_slave_config tx_conf;
|
||||
|
||||
u32 bw_speed_hz;
|
||||
};
|
||||
|
||||
static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer);
|
||||
@ -180,6 +187,23 @@ static inline bool spi_qup_is_valid_state(struct spi_qup *controller)
|
||||
return opstate & QUP_STATE_VALID;
|
||||
}
|
||||
|
||||
static int spi_qup_vote_bw(struct spi_qup *controller, u32 speed_hz)
|
||||
{
|
||||
u32 needed_peak_bw;
|
||||
int ret;
|
||||
|
||||
if (controller->bw_speed_hz == speed_hz)
|
||||
return 0;
|
||||
|
||||
needed_peak_bw = Bps_to_icc(speed_hz * SPI_BUS_WIDTH);
|
||||
ret = icc_set_bw(controller->icc_path, 0, needed_peak_bw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
controller->bw_speed_hz = speed_hz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spi_qup_set_state(struct spi_qup *controller, u32 state)
|
||||
{
|
||||
unsigned long loop;
|
||||
@ -450,6 +474,12 @@ static int spi_qup_do_dma(struct spi_device *spi, struct spi_transfer *xfer,
|
||||
struct scatterlist *tx_sgl, *rx_sgl;
|
||||
int ret;
|
||||
|
||||
ret = spi_qup_vote_bw(qup, xfer->speed_hz);
|
||||
if (ret) {
|
||||
dev_err(qup->dev, "fail to vote for ICC bandwidth: %d\n", ret);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (xfer->rx_buf)
|
||||
rx_done = spi_qup_dma_done;
|
||||
else if (xfer->tx_buf)
|
||||
@ -667,7 +697,7 @@ static int spi_qup_io_prep(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = clk_set_rate(controller->cclk, xfer->speed_hz);
|
||||
ret = dev_pm_opp_set_rate(controller->dev, xfer->speed_hz);
|
||||
if (ret) {
|
||||
dev_err(controller->dev, "fail to set frequency %d",
|
||||
xfer->speed_hz);
|
||||
@ -993,6 +1023,7 @@ static void spi_qup_set_cs(struct spi_device *spi, bool val)
|
||||
static int spi_qup_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_controller *host;
|
||||
struct icc_path *icc_path;
|
||||
struct clk *iclk, *cclk;
|
||||
struct spi_qup *controller;
|
||||
struct resource *res;
|
||||
@ -1018,6 +1049,11 @@ static int spi_qup_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(iclk))
|
||||
return PTR_ERR(iclk);
|
||||
|
||||
icc_path = devm_of_icc_get(dev, NULL);
|
||||
if (IS_ERR(icc_path))
|
||||
return dev_err_probe(dev, PTR_ERR(icc_path),
|
||||
"failed to get interconnect path\n");
|
||||
|
||||
/* This is optional parameter */
|
||||
if (of_property_read_u32(dev->of_node, "spi-max-frequency", &max_freq))
|
||||
max_freq = SPI_MAX_RATE;
|
||||
@ -1027,6 +1063,15 @@ static int spi_qup_probe(struct platform_device *pdev)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
ret = devm_pm_opp_set_clkname(dev, "core");
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* OPP table is optional */
|
||||
ret = devm_pm_opp_of_add_table(dev);
|
||||
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");
|
||||
@ -1060,6 +1105,7 @@ static int spi_qup_probe(struct platform_device *pdev)
|
||||
controller->base = base;
|
||||
controller->iclk = iclk;
|
||||
controller->cclk = cclk;
|
||||
controller->icc_path = icc_path;
|
||||
controller->irq = irq;
|
||||
|
||||
ret = spi_qup_init_dma(host, res->start);
|
||||
@ -1180,6 +1226,7 @@ static int spi_qup_pm_suspend_runtime(struct device *device)
|
||||
writel_relaxed(config, controller->base + QUP_CONFIG);
|
||||
|
||||
clk_disable_unprepare(controller->cclk);
|
||||
spi_qup_vote_bw(controller, 0);
|
||||
clk_disable_unprepare(controller->iclk);
|
||||
|
||||
return 0;
|
||||
@ -1231,6 +1278,7 @@ static int spi_qup_suspend(struct device *device)
|
||||
return ret;
|
||||
|
||||
clk_disable_unprepare(controller->cclk);
|
||||
spi_qup_vote_bw(controller, 0);
|
||||
clk_disable_unprepare(controller->iclk);
|
||||
return 0;
|
||||
}
|
||||
|
@ -782,42 +782,30 @@ static int rockchip_spi_probe(struct platform_device *pdev)
|
||||
goto err_put_ctlr;
|
||||
}
|
||||
|
||||
rs->apb_pclk = devm_clk_get(&pdev->dev, "apb_pclk");
|
||||
rs->apb_pclk = devm_clk_get_enabled(&pdev->dev, "apb_pclk");
|
||||
if (IS_ERR(rs->apb_pclk)) {
|
||||
dev_err(&pdev->dev, "Failed to get apb_pclk\n");
|
||||
ret = PTR_ERR(rs->apb_pclk);
|
||||
goto err_put_ctlr;
|
||||
}
|
||||
|
||||
rs->spiclk = devm_clk_get(&pdev->dev, "spiclk");
|
||||
rs->spiclk = devm_clk_get_enabled(&pdev->dev, "spiclk");
|
||||
if (IS_ERR(rs->spiclk)) {
|
||||
dev_err(&pdev->dev, "Failed to get spi_pclk\n");
|
||||
ret = PTR_ERR(rs->spiclk);
|
||||
goto err_put_ctlr;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(rs->apb_pclk);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to enable apb_pclk\n");
|
||||
goto err_put_ctlr;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(rs->spiclk);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to enable spi_clk\n");
|
||||
goto err_disable_apbclk;
|
||||
}
|
||||
|
||||
spi_enable_chip(rs, false);
|
||||
|
||||
ret = platform_get_irq(pdev, 0);
|
||||
if (ret < 0)
|
||||
goto err_disable_spiclk;
|
||||
goto err_put_ctlr;
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, ret, rockchip_spi_isr, NULL,
|
||||
IRQF_ONESHOT, dev_name(&pdev->dev), ctlr);
|
||||
if (ret)
|
||||
goto err_disable_spiclk;
|
||||
goto err_put_ctlr;
|
||||
|
||||
rs->dev = &pdev->dev;
|
||||
rs->freq = clk_get_rate(rs->spiclk);
|
||||
@ -843,7 +831,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
|
||||
if (!rs->fifo_len) {
|
||||
dev_err(&pdev->dev, "Failed to get fifo length\n");
|
||||
ret = -EINVAL;
|
||||
goto err_disable_spiclk;
|
||||
goto err_put_ctlr;
|
||||
}
|
||||
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev, ROCKCHIP_AUTOSUSPEND_TIMEOUT);
|
||||
@ -937,10 +925,6 @@ err_free_dma_tx:
|
||||
dma_release_channel(ctlr->dma_tx);
|
||||
err_disable_pm_runtime:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
err_disable_spiclk:
|
||||
clk_disable_unprepare(rs->spiclk);
|
||||
err_disable_apbclk:
|
||||
clk_disable_unprepare(rs->apb_pclk);
|
||||
err_put_ctlr:
|
||||
spi_controller_put(ctlr);
|
||||
|
||||
@ -950,13 +934,9 @@ err_put_ctlr:
|
||||
static void rockchip_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_controller *ctlr = spi_controller_get(platform_get_drvdata(pdev));
|
||||
struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
|
||||
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
|
||||
clk_disable_unprepare(rs->spiclk);
|
||||
clk_disable_unprepare(rs->apb_pclk);
|
||||
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/reset.h>
|
||||
@ -38,6 +39,9 @@
|
||||
#define CSI_MODE_SETUP 0x00000040
|
||||
|
||||
/* CSI_CLKSEL */
|
||||
#define CSI_CLKSEL_SS_ENA BIT(19)
|
||||
#define CSI_CLKSEL_SS_POL BIT(18)
|
||||
#define CSI_CLKSEL_SS (CSI_CLKSEL_SS_ENA | CSI_CLKSEL_SS_POL)
|
||||
#define CSI_CLKSEL_CKP BIT(17)
|
||||
#define CSI_CLKSEL_DAP BIT(16)
|
||||
#define CSI_CLKSEL_MODE (CSI_CLKSEL_CKP|CSI_CLKSEL_DAP)
|
||||
@ -82,6 +86,10 @@
|
||||
|
||||
#define CSI_MAX_SPI_SCKO (8 * HZ_PER_MHZ)
|
||||
|
||||
#define CSI_CLKSEL_SS_DISABLED 0
|
||||
#define CSI_CLKSEL_SS_ENABLED_ACTIVE_LOW BIT(1)
|
||||
#define CSI_CLKSEL_SS_ENABLED_ACTIVE_HIGH GENMASK(1, 0)
|
||||
|
||||
struct rzv2m_csi_priv {
|
||||
void __iomem *base;
|
||||
struct clk *csiclk;
|
||||
@ -99,6 +107,8 @@ struct rzv2m_csi_priv {
|
||||
wait_queue_head_t wait;
|
||||
u32 errors;
|
||||
u32 status;
|
||||
bool target_aborted;
|
||||
bool use_ss_pin;
|
||||
};
|
||||
|
||||
static void rzv2m_csi_reg_write_bit(const struct rzv2m_csi_priv *csi,
|
||||
@ -193,6 +203,14 @@ static int rzv2m_csi_read_rxfifo(struct rzv2m_csi_priv *csi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void rzv2m_csi_empty_rxfifo(struct rzv2m_csi_priv *csi)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < csi->words_to_transfer; i++)
|
||||
readl(csi->base + CSI_IFIFO);
|
||||
}
|
||||
|
||||
static inline void rzv2m_csi_calc_current_transfer(struct rzv2m_csi_priv *csi)
|
||||
{
|
||||
unsigned int bytes_transferred = max(csi->bytes_received, csi->bytes_sent);
|
||||
@ -279,32 +297,23 @@ static int rzv2m_csi_wait_for_interrupt(struct rzv2m_csi_priv *csi,
|
||||
|
||||
rzv2m_csi_enable_irqs(csi, enable_bits);
|
||||
|
||||
ret = wait_event_timeout(csi->wait,
|
||||
((csi->status & wait_mask) == wait_mask) ||
|
||||
csi->errors, HZ);
|
||||
if (spi_controller_is_target(csi->controller)) {
|
||||
ret = wait_event_interruptible(csi->wait,
|
||||
((csi->status & wait_mask) == wait_mask) ||
|
||||
csi->errors || csi->target_aborted);
|
||||
if (ret || csi->target_aborted)
|
||||
ret = -EINTR;
|
||||
} else {
|
||||
ret = wait_event_timeout(csi->wait,
|
||||
((csi->status & wait_mask) == wait_mask) ||
|
||||
csi->errors, HZ) == 0 ? -ETIMEDOUT : 0;
|
||||
}
|
||||
|
||||
rzv2m_csi_disable_irqs(csi, enable_bits);
|
||||
|
||||
if (csi->errors)
|
||||
return -EIO;
|
||||
|
||||
if (!ret)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rzv2m_csi_wait_for_tx_empty(struct rzv2m_csi_priv *csi)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (readl(csi->base + CSI_OFIFOL) == 0)
|
||||
return 0;
|
||||
|
||||
ret = rzv2m_csi_wait_for_interrupt(csi, CSI_INT_TREND, CSI_CNT_TREND_E);
|
||||
if (ret == -ETIMEDOUT)
|
||||
csi->errors |= TX_TIMEOUT_ERROR;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -312,7 +321,7 @@ static inline int rzv2m_csi_wait_for_rx_ready(struct rzv2m_csi_priv *csi)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (readl(csi->base + CSI_IFIFOL) == csi->bytes_to_transfer)
|
||||
if (readl(csi->base + CSI_IFIFOL) >= csi->bytes_to_transfer)
|
||||
return 0;
|
||||
|
||||
ret = rzv2m_csi_wait_for_interrupt(csi, CSI_INT_R_TRGR,
|
||||
@ -388,6 +397,7 @@ static void rzv2m_csi_setup_operating_mode(struct rzv2m_csi_priv *csi,
|
||||
static int rzv2m_csi_setup(struct spi_device *spi)
|
||||
{
|
||||
struct rzv2m_csi_priv *csi = spi_controller_get_devdata(spi->controller);
|
||||
u32 slave_selection = CSI_CLKSEL_SS_DISABLED;
|
||||
int ret;
|
||||
|
||||
rzv2m_csi_sw_reset(csi, 0);
|
||||
@ -402,8 +412,17 @@ static int rzv2m_csi_setup(struct spi_device *spi)
|
||||
rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_DIR,
|
||||
!!(spi->mode & SPI_LSB_FIRST));
|
||||
|
||||
/* Set the operation mode as master */
|
||||
rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_SLAVE, 0);
|
||||
/* Set the role, 1 for target and 0 for host */
|
||||
rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_SLAVE,
|
||||
!!spi_controller_is_target(csi->controller));
|
||||
|
||||
if (csi->use_ss_pin)
|
||||
slave_selection = spi->mode & SPI_CS_HIGH ?
|
||||
CSI_CLKSEL_SS_ENABLED_ACTIVE_HIGH :
|
||||
CSI_CLKSEL_SS_ENABLED_ACTIVE_LOW;
|
||||
|
||||
/* Configure the slave selection (SS) pin */
|
||||
rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_SS, slave_selection);
|
||||
|
||||
/* Give the IP a SW reset */
|
||||
ret = rzv2m_csi_sw_reset(csi, 1);
|
||||
@ -431,9 +450,13 @@ static int rzv2m_csi_pio_transfer(struct rzv2m_csi_priv *csi)
|
||||
/* Make sure the TX FIFO is empty */
|
||||
writel(0, csi->base + CSI_OFIFOL);
|
||||
|
||||
/* Make sure the RX FIFO is empty */
|
||||
writel(0, csi->base + CSI_IFIFOL);
|
||||
|
||||
csi->bytes_sent = 0;
|
||||
csi->bytes_received = 0;
|
||||
csi->errors = 0;
|
||||
csi->target_aborted = false;
|
||||
|
||||
rzv2m_csi_disable_all_irqs(csi);
|
||||
rzv2m_csi_clear_all_irqs(csi);
|
||||
@ -452,28 +475,21 @@ static int rzv2m_csi_pio_transfer(struct rzv2m_csi_priv *csi)
|
||||
|
||||
rzv2m_csi_enable_irqs(csi, CSI_INT_OVERF | CSI_INT_UNDER);
|
||||
|
||||
/* Make sure the RX FIFO is empty */
|
||||
writel(0, csi->base + CSI_IFIFOL);
|
||||
|
||||
writel(readl(csi->base + CSI_INT), csi->base + CSI_INT);
|
||||
csi->status = 0;
|
||||
|
||||
rzv2m_csi_start_stop_operation(csi, 1, false);
|
||||
|
||||
/* TX */
|
||||
if (csi->txbuf) {
|
||||
ret = rzv2m_csi_fill_txfifo(csi);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
ret = rzv2m_csi_wait_for_tx_empty(csi);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
if (csi->bytes_sent == csi->buffer_len)
|
||||
tx_completed = true;
|
||||
}
|
||||
|
||||
rzv2m_csi_start_stop_operation(csi, 1, false);
|
||||
|
||||
/*
|
||||
* Make sure the RX FIFO contains the desired number of words.
|
||||
* We then either flush its content, or we copy it onto
|
||||
@ -483,31 +499,28 @@ static int rzv2m_csi_pio_transfer(struct rzv2m_csi_priv *csi)
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
/* RX */
|
||||
if (csi->rxbuf) {
|
||||
if (!spi_controller_is_target(csi->controller))
|
||||
rzv2m_csi_start_stop_operation(csi, 0, false);
|
||||
|
||||
/* RX */
|
||||
if (csi->rxbuf) {
|
||||
ret = rzv2m_csi_read_rxfifo(csi);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
if (csi->bytes_received == csi->buffer_len)
|
||||
rx_completed = true;
|
||||
} else {
|
||||
rzv2m_csi_empty_rxfifo(csi);
|
||||
}
|
||||
|
||||
ret = rzv2m_csi_start_stop_operation(csi, 0, true);
|
||||
if (ret)
|
||||
goto pio_quit;
|
||||
|
||||
if (csi->errors) {
|
||||
ret = -EIO;
|
||||
goto pio_quit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rzv2m_csi_start_stop_operation(csi, 0, true);
|
||||
|
||||
pio_quit:
|
||||
rzv2m_csi_disable_all_irqs(csi);
|
||||
rzv2m_csi_enable_rx_trigger(csi, false);
|
||||
rzv2m_csi_clear_all_irqs(csi);
|
||||
@ -529,7 +542,8 @@ static int rzv2m_csi_transfer_one(struct spi_controller *controller,
|
||||
|
||||
rzv2m_csi_setup_operating_mode(csi, transfer);
|
||||
|
||||
rzv2m_csi_setup_clock(csi, transfer->speed_hz);
|
||||
if (!spi_controller_is_target(csi->controller))
|
||||
rzv2m_csi_setup_clock(csi, transfer->speed_hz);
|
||||
|
||||
ret = rzv2m_csi_pio_transfer(csi);
|
||||
if (ret) {
|
||||
@ -546,24 +560,48 @@ static int rzv2m_csi_transfer_one(struct spi_controller *controller,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rzv2m_csi_target_abort(struct spi_controller *ctlr)
|
||||
{
|
||||
struct rzv2m_csi_priv *csi = spi_controller_get_devdata(ctlr);
|
||||
|
||||
csi->target_aborted = true;
|
||||
wake_up(&csi->wait);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rzv2m_csi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct spi_controller *controller;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct rzv2m_csi_priv *csi;
|
||||
struct reset_control *rstc;
|
||||
bool target_mode;
|
||||
int irq;
|
||||
int ret;
|
||||
|
||||
controller = devm_spi_alloc_host(dev, sizeof(*csi));
|
||||
target_mode = of_property_read_bool(np, "spi-slave");
|
||||
|
||||
if (target_mode)
|
||||
controller = devm_spi_alloc_target(dev, sizeof(*csi));
|
||||
else
|
||||
controller = devm_spi_alloc_host(dev, sizeof(*csi));
|
||||
|
||||
if (!controller)
|
||||
return -ENOMEM;
|
||||
|
||||
csi = spi_controller_get_devdata(controller);
|
||||
platform_set_drvdata(pdev, csi);
|
||||
|
||||
csi->use_ss_pin = false;
|
||||
if (spi_controller_is_target(controller) &&
|
||||
!of_property_read_bool(np, "renesas,csi-no-ss"))
|
||||
csi->use_ss_pin = true;
|
||||
|
||||
csi->dev = dev;
|
||||
csi->controller = controller;
|
||||
csi->target_aborted = false;
|
||||
|
||||
csi->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(csi->base))
|
||||
@ -589,11 +627,12 @@ static int rzv2m_csi_probe(struct platform_device *pdev)
|
||||
|
||||
init_waitqueue_head(&csi->wait);
|
||||
|
||||
controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
|
||||
controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH;
|
||||
controller->bits_per_word_mask = SPI_BPW_MASK(16) | SPI_BPW_MASK(8);
|
||||
controller->setup = rzv2m_csi_setup;
|
||||
controller->transfer_one = rzv2m_csi_transfer_one;
|
||||
controller->use_gpio_descriptors = true;
|
||||
controller->target_abort = rzv2m_csi_target_abort;
|
||||
|
||||
device_set_node(&controller->dev, dev_fwnode(dev));
|
||||
|
||||
|
@ -13,7 +13,8 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/reset.h>
|
||||
|
@ -1086,6 +1086,8 @@ static int tegra_slink_probe(struct platform_device *pdev)
|
||||
reset_control_deassert(tspi->rst);
|
||||
|
||||
spi_irq = platform_get_irq(pdev, 0);
|
||||
if (spi_irq < 0)
|
||||
return spi_irq;
|
||||
tspi->irq = spi_irq;
|
||||
ret = request_threaded_irq(tspi->irq, tegra_slink_isr,
|
||||
tegra_slink_isr_thread, IRQF_ONESHOT,
|
||||
|
@ -2093,10 +2093,6 @@ static int spi_stop_queue(struct spi_controller *ctlr)
|
||||
|
||||
spin_unlock_irqrestore(&ctlr->queue_lock, flags);
|
||||
|
||||
if (ret) {
|
||||
dev_warn(&ctlr->dev, "could not stop message queue\n");
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2527,8 +2523,6 @@ static void acpi_spi_parse_apple_properties(struct acpi_device *dev,
|
||||
lookup->mode |= SPI_CPHA;
|
||||
}
|
||||
|
||||
static struct spi_controller *acpi_spi_find_controller_by_adev(struct acpi_device *adev);
|
||||
|
||||
static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)
|
||||
{
|
||||
struct acpi_spi_lookup *lookup = data;
|
||||
@ -4523,7 +4517,7 @@ static int spi_acpi_controller_match(struct device *dev, const void *data)
|
||||
return ACPI_COMPANION(dev->parent) == data;
|
||||
}
|
||||
|
||||
static struct spi_controller *acpi_spi_find_controller_by_adev(struct acpi_device *adev)
|
||||
struct spi_controller *acpi_spi_find_controller_by_adev(struct acpi_device *adev)
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
@ -4537,6 +4531,7 @@ static struct spi_controller *acpi_spi_find_controller_by_adev(struct acpi_devic
|
||||
|
||||
return container_of(dev, struct spi_controller, dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_spi_find_controller_by_adev);
|
||||
|
||||
static struct spi_device *acpi_spi_find_device_by_adev(struct acpi_device *adev)
|
||||
{
|
||||
|
@ -357,6 +357,7 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
int retval = 0;
|
||||
struct spidev_data *spidev;
|
||||
struct spi_device *spi;
|
||||
struct spi_controller *ctlr;
|
||||
u32 tmp;
|
||||
unsigned n_ioc;
|
||||
struct spi_ioc_transfer *ioc;
|
||||
@ -376,6 +377,8 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
return -ESHUTDOWN;
|
||||
}
|
||||
|
||||
ctlr = spi->controller;
|
||||
|
||||
/* use the buffer lock here for triple duty:
|
||||
* - prevent I/O (from us) so calling spi_setup() is safe;
|
||||
* - prevent concurrent SPI_IOC_WR_* from morphing
|
||||
@ -388,22 +391,15 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
/* read requests */
|
||||
case SPI_IOC_RD_MODE:
|
||||
case SPI_IOC_RD_MODE32:
|
||||
tmp = spi->mode;
|
||||
tmp = spi->mode & SPI_MODE_MASK;
|
||||
|
||||
{
|
||||
struct spi_controller *ctlr = spi->controller;
|
||||
|
||||
if (ctlr->use_gpio_descriptors && ctlr->cs_gpiods &&
|
||||
ctlr->cs_gpiods[spi_get_chipselect(spi, 0)])
|
||||
tmp &= ~SPI_CS_HIGH;
|
||||
}
|
||||
if (ctlr->use_gpio_descriptors && spi_get_csgpiod(spi, 0))
|
||||
tmp &= ~SPI_CS_HIGH;
|
||||
|
||||
if (cmd == SPI_IOC_RD_MODE)
|
||||
retval = put_user(tmp & SPI_MODE_MASK,
|
||||
(__u8 __user *)arg);
|
||||
retval = put_user(tmp, (__u8 __user *)arg);
|
||||
else
|
||||
retval = put_user(tmp & SPI_MODE_MASK,
|
||||
(__u32 __user *)arg);
|
||||
retval = put_user(tmp, (__u32 __user *)arg);
|
||||
break;
|
||||
case SPI_IOC_RD_LSB_FIRST:
|
||||
retval = put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0,
|
||||
@ -424,7 +420,6 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
else
|
||||
retval = get_user(tmp, (u32 __user *)arg);
|
||||
if (retval == 0) {
|
||||
struct spi_controller *ctlr = spi->controller;
|
||||
u32 save = spi->mode;
|
||||
|
||||
if (tmp & ~SPI_MODE_MASK) {
|
||||
@ -432,8 +427,7 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ctlr->use_gpio_descriptors && ctlr->cs_gpiods &&
|
||||
ctlr->cs_gpiods[spi_get_chipselect(spi, 0)])
|
||||
if (ctlr->use_gpio_descriptors && spi_get_csgpiod(spi, 0))
|
||||
tmp |= SPI_CS_HIGH;
|
||||
|
||||
tmp |= spi->mode & ~SPI_MODE_MASK;
|
||||
@ -701,7 +695,9 @@ static const struct file_operations spidev_fops = {
|
||||
* It also simplifies memory management.
|
||||
*/
|
||||
|
||||
static struct class *spidev_class;
|
||||
static const struct class spidev_class = {
|
||||
.name = "spidev",
|
||||
};
|
||||
|
||||
static const struct spi_device_id spidev_spi_ids[] = {
|
||||
{ .name = "dh2228fv" },
|
||||
@ -804,7 +800,7 @@ static int spidev_probe(struct spi_device *spi)
|
||||
struct device *dev;
|
||||
|
||||
spidev->devt = MKDEV(SPIDEV_MAJOR, minor);
|
||||
dev = device_create(spidev_class, &spi->dev, spidev->devt,
|
||||
dev = device_create(&spidev_class, &spi->dev, spidev->devt,
|
||||
spidev, "spidev%d.%d",
|
||||
spi->master->bus_num, spi_get_chipselect(spi, 0));
|
||||
status = PTR_ERR_OR_ZERO(dev);
|
||||
@ -840,7 +836,7 @@ static void spidev_remove(struct spi_device *spi)
|
||||
mutex_unlock(&spidev->spi_lock);
|
||||
|
||||
list_del(&spidev->device_entry);
|
||||
device_destroy(spidev_class, spidev->devt);
|
||||
device_destroy(&spidev_class, spidev->devt);
|
||||
clear_bit(MINOR(spidev->devt), minors);
|
||||
if (spidev->users == 0)
|
||||
kfree(spidev);
|
||||
@ -878,15 +874,15 @@ static int __init spidev_init(void)
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
spidev_class = class_create("spidev");
|
||||
if (IS_ERR(spidev_class)) {
|
||||
status = class_register(&spidev_class);
|
||||
if (status) {
|
||||
unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
|
||||
return PTR_ERR(spidev_class);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = spi_register_driver(&spidev_spi_driver);
|
||||
if (status < 0) {
|
||||
class_destroy(spidev_class);
|
||||
class_unregister(&spidev_class);
|
||||
unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
|
||||
}
|
||||
return status;
|
||||
@ -896,7 +892,7 @@ module_init(spidev_init);
|
||||
static void __exit spidev_exit(void)
|
||||
{
|
||||
spi_unregister_driver(&spidev_spi_driver);
|
||||
class_destroy(spidev_class);
|
||||
class_unregister(&spidev_class);
|
||||
unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
|
||||
}
|
||||
module_exit(spidev_exit);
|
||||
|
@ -867,6 +867,7 @@ extern int devm_spi_register_controller(struct device *dev,
|
||||
extern void spi_unregister_controller(struct spi_controller *ctlr);
|
||||
|
||||
#if IS_ENABLED(CONFIG_ACPI)
|
||||
extern struct spi_controller *acpi_spi_find_controller_by_adev(struct acpi_device *adev);
|
||||
extern struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr,
|
||||
struct acpi_device *adev,
|
||||
int index);
|
||||
@ -1086,8 +1087,6 @@ struct spi_transfer {
|
||||
* @state: for use by whichever driver currently owns the message
|
||||
* @resources: for resource management when the SPI message is processed
|
||||
* @prepared: spi_prepare_message was called for the this message
|
||||
* @t: for use with spi_message_alloc() when message and transfers have
|
||||
* been allocated together
|
||||
*
|
||||
* A @spi_message is used to execute an atomic sequence of data transfers,
|
||||
* each represented by a struct spi_transfer. The sequence is "atomic"
|
||||
@ -1142,9 +1141,6 @@ struct spi_message {
|
||||
|
||||
/* List of spi_res resources when the SPI message is processed */
|
||||
struct list_head resources;
|
||||
|
||||
/* For embedding transfers into the memory of the message */
|
||||
struct spi_transfer t[];
|
||||
};
|
||||
|
||||
static inline void spi_message_init_no_memset(struct spi_message *m)
|
||||
@ -1203,17 +1199,21 @@ struct spi_transfer *xfers, unsigned int num_xfers)
|
||||
*/
|
||||
static inline struct spi_message *spi_message_alloc(unsigned ntrans, gfp_t flags)
|
||||
{
|
||||
struct spi_message *m;
|
||||
struct spi_message_with_transfers {
|
||||
struct spi_message m;
|
||||
struct spi_transfer t[];
|
||||
} *mwt;
|
||||
unsigned i;
|
||||
|
||||
m = kzalloc(struct_size(m, t, ntrans), flags);
|
||||
if (m) {
|
||||
unsigned i;
|
||||
mwt = kzalloc(struct_size(mwt, t, ntrans), flags);
|
||||
if (!mwt)
|
||||
return NULL;
|
||||
|
||||
spi_message_init_no_memset(m);
|
||||
for (i = 0; i < ntrans; i++)
|
||||
spi_message_add_tail(&m->t[i], m);
|
||||
}
|
||||
return m;
|
||||
spi_message_init_no_memset(&mwt->m);
|
||||
for (i = 0; i < ntrans; i++)
|
||||
spi_message_add_tail(&mwt->t[i], &mwt->m);
|
||||
|
||||
return &mwt->m;
|
||||
}
|
||||
|
||||
static inline void spi_message_free(struct spi_message *m)
|
||||
|
Loading…
x
Reference in New Issue
Block a user