Merge ce51c2b7ce ("Merge tag 'mmc-v5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc") into android-mainline

Steps on the way to 5.11-rc1

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: I2bac328ace91118b026621b8544019c3ca472d88
This commit is contained in:
Greg Kroah-Hartman 2020-12-18 15:11:27 +01:00
commit 8b882de4c1
77 changed files with 1443 additions and 794 deletions

View File

@ -5,8 +5,12 @@ Required properties:
"aeroflexgaisler,i2cmst"
"sifive,fu540-c000-i2c", "sifive,i2c0"
For Opencore based I2C IP block reimplemented in
FU540-C000 SoC. Please refer to sifive-blocks-ip-versioning.txt
for additional details.
FU540-C000 SoC.
"sifive,fu740-c000-i2c", "sifive,i2c0"
For Opencore based I2C IP block reimplemented in
FU740-C000 SoC.
Please refer to sifive-blocks-ip-versioning.txt for
additional details.
- reg : bus address start and address range size of device
- clocks : handle to the controller clock; see the note below.
Mutually exclusive with opencores,ip-clock-frequency

View File

@ -8,6 +8,7 @@ Required properties :
"ti,omap4-i2c" for OMAP4+ SoCs
"ti,am654-i2c", "ti,omap4-i2c" for AM654 SoCs
"ti,j721e-i2c", "ti,omap4-i2c" for J721E SoCs
"ti,am64-i2c", "ti,omap4-i2c" for AM64 SoCs
- ti,hwmods : Must be "i2c<n>", n being the instance number (1-based)
- #address-cells = <1>;
- #size-cells = <0>;

View File

@ -1,29 +0,0 @@
Actions Semiconductor Owl I2C controller
Required properties:
- compatible : Should be one of the following:
- "actions,s700-i2c" for S700 SoC
- "actions,s900-i2c" for S900 SoC
- reg : Offset and length of the register set for the device.
- #address-cells : Should be 1.
- #size-cells : Should be 0.
- interrupts : A single interrupt specifier.
- clocks : Phandle of the clock feeding the I2C controller.
Optional properties:
- clock-frequency : Desired I2C bus clock frequency in Hz. As only Normal and
Fast modes are supported, possible values are 100000 and
400000.
Examples:
i2c0: i2c@e0170000 {
compatible = "actions,s900-i2c";
reg = <0 0xe0170000 0 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clock CLK_I2C0>;
clock-frequency = <100000>;
};

View File

@ -0,0 +1,62 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/i2c/i2c-owl.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Actions Semi Owl I2C Controller
maintainers:
- Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
description: |
This I2C controller is found in the Actions Semi Owl SoCs:
S500, S700 and S900.
allOf:
- $ref: /schemas/i2c/i2c-controller.yaml#
properties:
compatible:
enum:
- actions,s500-i2c # Actions Semi S500 compatible SoCs
- actions,s700-i2c # Actions Semi S700 compatible SoCs
- actions,s900-i2c # Actions Semi S900 compatible SoCs
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
description: Phandle of the clock feeding the I2C controller.
minItems: 1
clock-frequency:
description: |
Desired I2C bus clock frequency in Hz. As only Standard and Fast
modes are supported, possible values are 100000 and 400000.
enum: [100000, 400000]
required:
- compatible
- reg
- interrupts
- clocks
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/actions,s900-cmu.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
i2c@e0170000 {
compatible = "actions,s900-i2c";
reg = <0xe0170000 0x1000>;
interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cmu CLK_I2C0>;
clock-frequency = <100000>;
};
...

View File

@ -1,42 +0,0 @@
Device tree configuration for the Mellanox I2C SMBus on BlueField SoCs
Required Properties:
- compatible : should be "mellanox,i2c-mlxbf1" or "mellanox,i2c-mlxbf2".
- reg : address offset and length of the device registers. The
registers consist of the following set of resources:
1) Smbus block registers.
2) Cause master registers.
3) Cause slave registers.
4) Cause coalesce registers (if compatible isn't set
to "mellanox,i2c-mlxbf1").
- interrupts : interrupt number.
Optional Properties:
- clock-frequency : bus frequency used to configure timing registers;
allowed values are 100000, 400000 and 1000000;
those are expressed in Hz. Default is 100000.
Example:
i2c@2804000 {
compatible = "mellanox,i2c-mlxbf1";
reg = <0x02804000 0x800>,
<0x02801200 0x020>,
<0x02801260 0x020>;
interrupts = <57>;
clock-frequency = <100000>;
};
i2c@2808800 {
compatible = "mellanox,i2c-mlxbf2";
reg = <0x02808800 0x600>,
<0x02808e00 0x020>,
<0x02808e20 0x020>,
<0x02808e40 0x010>;
interrupts = <57>;
clock-frequency = <400000>;
};

View File

@ -0,0 +1,78 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/i2c/mellanox,i2c-mlxbf.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Mellanox I2C SMBus on BlueField SoCs
maintainers:
- Khalil Blaiech <kblaiech@nvidia.com>
allOf:
- $ref: /schemas/i2c/i2c-controller.yaml#
properties:
compatible:
enum:
- mellanox,i2c-mlxbf1
- mellanox,i2c-mlxbf2
reg:
minItems: 3
maxItems: 4
items:
- description: Smbus block registers
- description: Cause master registers
- description: Cause slave registers
- description: Cause coalesce registers
interrupts:
maxItems: 1
clock-frequency:
enum: [ 100000, 400000, 1000000 ]
description:
bus frequency used to configure timing registers;
The frequency is expressed in Hz. Default is 100000.
required:
- compatible
- reg
- interrupts
unevaluatedProperties: false
if:
properties:
compatible:
contains:
enum:
- mellanox,i2c-mlxbf1
then:
properties:
reg:
maxItems: 3
examples:
- |
i2c@2804000 {
compatible = "mellanox,i2c-mlxbf1";
reg = <0x02804000 0x800>,
<0x02801200 0x020>,
<0x02801260 0x020>;
interrupts = <57>;
clock-frequency = <100000>;
};
- |
i2c@2808800 {
compatible = "mellanox,i2c-mlxbf2";
reg = <0x02808800 0x600>,
<0x02808e00 0x020>,
<0x02808e20 0x020>,
<0x02808e40 0x010>;
interrupts = <57>;
clock-frequency = <400000>;
};

View File

@ -147,7 +147,7 @@ properties:
xlnx,mio-bank:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 2]
enum: [0, 1, 2]
default: 0
description:
The MIO bank number in which the command and data lines are configured.

View File

@ -39,6 +39,7 @@ properties:
- fsl,imx8mn-usdhc
- fsl,imx8mp-usdhc
- fsl,imx8mq-usdhc
- fsl,imx8qm-usdhc
- fsl,imx8qxp-usdhc
- const: fsl,imx7d-usdhc

View File

@ -1,75 +0,0 @@
* MTK MMC controller
The MTK MSDC can act as a MMC controller
to support MMC, SD, and SDIO types of memory cards.
This file documents differences between the core properties in mmc.txt
and the properties used by the msdc driver.
Required properties:
- compatible: value should be either of the following.
"mediatek,mt8135-mmc": for mmc host ip compatible with mt8135
"mediatek,mt8173-mmc": for mmc host ip compatible with mt8173
"mediatek,mt8183-mmc": for mmc host ip compatible with mt8183
"mediatek,mt8516-mmc": for mmc host ip compatible with mt8516
"mediatek,mt6779-mmc": for mmc host ip compatible with mt6779
"mediatek,mt2701-mmc": for mmc host ip compatible with mt2701
"mediatek,mt2712-mmc": for mmc host ip compatible with mt2712
"mediatek,mt7622-mmc": for MT7622 SoC
"mediatek,mt7623-mmc", "mediatek,mt2701-mmc": for MT7623 SoC
"mediatek,mt7620-mmc", for MT7621 SoC (and others)
- reg: physical base address of the controller and length
- interrupts: Should contain MSDC interrupt number
- clocks: Should contain phandle for the clock feeding the MMC controller
- clock-names: Should contain the following:
"source" - source clock (required)
"hclk" - HCLK which used for host (required)
"source_cg" - independent source clock gate (required for MT2712)
"bus_clk" - bus clock used for internal register access (required for MT2712 MSDC0/3)
- pinctrl-names: should be "default", "state_uhs"
- pinctrl-0: should contain default/high speed pin ctrl
- pinctrl-1: should contain uhs mode pin ctrl
- vmmc-supply: power to the Core
- vqmmc-supply: power to the IO
Optional properties:
- assigned-clocks: PLL of the source clock
- assigned-clock-parents: parent of source clock, used for HS400 mode to get 400Mhz source clock
- hs400-ds-delay: HS400 DS delay setting
- mediatek,hs200-cmd-int-delay: HS200 command internal delay setting.
This field has total 32 stages.
The value is an integer from 0 to 31.
- mediatek,hs400-cmd-int-delay: HS400 command internal delay setting
This field has total 32 stages.
The value is an integer from 0 to 31.
- mediatek,hs400-cmd-resp-sel-rising: HS400 command response sample selection
If present,HS400 command responses are sampled on rising edges.
If not present,HS400 command responses are sampled on falling edges.
- mediatek,latch-ck: Some SoCs do not support enhance_rx, need set correct latch-ck to avoid data crc
error caused by stop clock(fifo full)
Valid range = [0:0x7]. if not present, default value is 0.
applied to compatible "mediatek,mt2701-mmc".
- resets: Phandle and reset specifier pair to softreset line of MSDC IP.
- reset-names: Should be "hrst".
Examples:
mmc0: mmc@11230000 {
compatible = "mediatek,mt8173-mmc", "mediatek,mt8135-mmc";
reg = <0 0x11230000 0 0x108>;
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_LOW>;
vmmc-supply = <&mt6397_vemc_3v3_reg>;
vqmmc-supply = <&mt6397_vio18_reg>;
clocks = <&pericfg CLK_PERI_MSDC30_0>,
<&topckgen CLK_TOP_MSDC50_0_H_SEL>;
clock-names = "source", "hclk";
pinctrl-names = "default", "state_uhs";
pinctrl-0 = <&mmc0_pins_default>;
pinctrl-1 = <&mmc0_pins_uhs>;
assigned-clocks = <&topckgen CLK_TOP_MSDC50_0_SEL>;
assigned-clock-parents = <&topckgen CLK_TOP_MSDCPLL_D2>;
hs400-ds-delay = <0x14015>;
mediatek,hs200-cmd-int-delay = <26>;
mediatek,hs400-cmd-int-delay = <14>;
mediatek,hs400-cmd-resp-sel-rising;
};

View File

@ -0,0 +1,176 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/mmc/mtk-sd.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MTK MSDC Storage Host Controller Binding
maintainers:
- Chaotian Jing <chaotian.jing@mediatek.com>
- Wenbin Mei <wenbin.mei@mediatek.com>
allOf:
- $ref: mmc-controller.yaml#
properties:
compatible:
oneOf:
- enum:
- mediatek,mt2701-mmc
- mediatek,mt2712-mmc
- mediatek,mt6779-mmc
- mediatek,mt7620-mmc
- mediatek,mt7622-mmc
- mediatek,mt8135-mmc
- mediatek,mt8173-mmc
- mediatek,mt8183-mmc
- mediatek,mt8516-mmc
- items:
- const: mediatek,mt7623-mmc
- const: mediatek,mt2701-mmc
- items:
- const: mediatek,mt8192-mmc
- const: mediatek,mt8183-mmc
clocks:
description:
Should contain phandle for the clock feeding the MMC controller.
minItems: 2
maxItems: 8
items:
- description: source clock (required).
- description: HCLK which used for host (required).
- description: independent source clock gate (required for MT2712).
- description: bus clock used for internal register access (required for MT2712 MSDC0/3).
- description: msdc subsys clock gate (required for MT8192).
- description: peripheral bus clock gate (required for MT8192).
- description: AXI bus clock gate (required for MT8192).
- description: AHB bus clock gate (required for MT8192).
clock-names:
minItems: 2
maxItems: 8
items:
- const: source
- const: hclk
- const: source_cg
- const: bus_clk
- const: sys_cg
- const: pclk_cg
- const: axi_cg
- const: ahb_cg
pinctrl-names:
items:
- const: default
- const: state_uhs
pinctrl-0:
description:
should contain default/high speed pin ctrl.
maxItems: 1
pinctrl-1:
description:
should contain uhs mode pin ctrl.
maxItems: 1
assigned-clocks:
description:
PLL of the source clock.
maxItems: 1
assigned-clock-parents:
description:
parent of source clock, used for HS400 mode to get 400Mhz source clock.
maxItems: 1
hs400-ds-delay:
$ref: /schemas/types.yaml#/definitions/uint32
description:
HS400 DS delay setting.
minimum: 0
maximum: 0xffffffff
mediatek,hs200-cmd-int-delay:
$ref: /schemas/types.yaml#/definitions/uint32
description:
HS200 command internal delay setting.
This field has total 32 stages.
The value is an integer from 0 to 31.
minimum: 0
maximum: 31
mediatek,hs400-cmd-int-delay:
$ref: /schemas/types.yaml#/definitions/uint32
description:
HS400 command internal delay setting.
This field has total 32 stages.
The value is an integer from 0 to 31.
minimum: 0
maximum: 31
mediatek,hs400-cmd-resp-sel-rising:
$ref: /schemas/types.yaml#/definitions/flag
description:
HS400 command response sample selection.
If present, HS400 command responses are sampled on rising edges.
If not present, HS400 command responses are sampled on falling edges.
mediatek,latch-ck:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Some SoCs do not support enhance_rx, need set correct latch-ck to avoid
data crc error caused by stop clock(fifo full) Valid range = [0:0x7].
if not present, default value is 0.
applied to compatible "mediatek,mt2701-mmc".
minimum: 0
maximum: 7
resets:
maxItems: 1
reset-names:
const: hrst
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- pinctrl-names
- pinctrl-0
- pinctrl-1
- vmmc-supply
- vqmmc-supply
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/mt8173-clk.h>
mmc0: mmc@11230000 {
compatible = "mediatek,mt8173-mmc";
reg = <0x11230000 0x1000>;
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_LOW>;
vmmc-supply = <&mt6397_vemc_3v3_reg>;
vqmmc-supply = <&mt6397_vio18_reg>;
clocks = <&pericfg CLK_PERI_MSDC30_0>,
<&topckgen CLK_TOP_MSDC50_0_H_SEL>;
clock-names = "source", "hclk";
pinctrl-names = "default", "state_uhs";
pinctrl-0 = <&mmc0_pins_default>;
pinctrl-1 = <&mmc0_pins_uhs>;
assigned-clocks = <&topckgen CLK_TOP_MSDC50_0_SEL>;
assigned-clock-parents = <&topckgen CLK_TOP_MSDCPLL_D2>;
hs400-ds-delay = <0x14015>;
mediatek,hs200-cmd-int-delay = <26>;
mediatek,hs400-cmd-int-delay = <14>;
mediatek,hs400-cmd-resp-sel-rising;
};
...

View File

@ -17,7 +17,9 @@ properties:
oneOf:
- const: actions,owl-mmc
- items:
- const: actions,s700-mmc
- enum:
- actions,s500-mmc
- actions,s700-mmc
- const: actions,owl-mmc
reg:

View File

@ -1502,7 +1502,7 @@ S: Maintained
F: Documentation/devicetree/bindings/arm/actions.yaml
F: Documentation/devicetree/bindings/clock/actions,owl-cmu.txt
F: Documentation/devicetree/bindings/dma/owl-dma.yaml
F: Documentation/devicetree/bindings/i2c/i2c-owl.txt
F: Documentation/devicetree/bindings/i2c/i2c-owl.yaml
F: Documentation/devicetree/bindings/interrupt-controller/actions,owl-sirq.yaml
F: Documentation/devicetree/bindings/mmc/owl-mmc.yaml
F: Documentation/devicetree/bindings/pinctrl/actions,*
@ -11261,6 +11261,7 @@ MELLANOX BLUEFIELD I2C DRIVER
M: Khalil Blaiech <kblaiech@nvidia.com>
L: linux-i2c@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml
F: drivers/i2c/busses/i2c-mlxbf.c
MELLANOX ETHERNET DRIVER (mlx4_en)

View File

@ -675,6 +675,7 @@ config I2C_IMG
config I2C_IMX
tristate "IMX I2C interface"
depends on ARCH_MXC || ARCH_LAYERSCAPE || COLDFIRE
select I2C_SLAVE
help
Say Y here if you want to use the IIC bus controller on
the Freescale i.MX/MXC, Layerscape or ColdFire processors.

View File

@ -26,7 +26,6 @@
#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/platform_data/dma-atmel.h>
#include <linux/pm_runtime.h>
#include "i2c-at91.h"

View File

@ -18,7 +18,6 @@
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/i2c.h>
#include <linux/platform_data/dma-atmel.h>
#include <linux/platform_device.h>
#define AT91_I2C_TIMEOUT msecs_to_jiffies(100) /* transfer timeout */
@ -123,7 +122,6 @@ struct at91_twi_pdata {
bool has_adv_dig_filtr;
bool has_ana_filtr;
bool has_clear_cmd;
struct at_dma_slave dma_slave;
};
struct at91_twi_dma {

View File

@ -25,25 +25,25 @@
I2C_FUNC_SMBUS_BLOCK_DATA | \
I2C_FUNC_SMBUS_I2C_BLOCK)
#define DW_IC_CON_MASTER 0x1
#define DW_IC_CON_SPEED_STD 0x2
#define DW_IC_CON_SPEED_FAST 0x4
#define DW_IC_CON_SPEED_HIGH 0x6
#define DW_IC_CON_SPEED_MASK 0x6
#define DW_IC_CON_10BITADDR_SLAVE 0x8
#define DW_IC_CON_10BITADDR_MASTER 0x10
#define DW_IC_CON_RESTART_EN 0x20
#define DW_IC_CON_SLAVE_DISABLE 0x40
#define DW_IC_CON_STOP_DET_IFADDRESSED 0x80
#define DW_IC_CON_TX_EMPTY_CTRL 0x100
#define DW_IC_CON_RX_FIFO_FULL_HLD_CTRL 0x200
#define DW_IC_CON_MASTER BIT(0)
#define DW_IC_CON_SPEED_STD (1 << 1)
#define DW_IC_CON_SPEED_FAST (2 << 1)
#define DW_IC_CON_SPEED_HIGH (3 << 1)
#define DW_IC_CON_SPEED_MASK GENMASK(2, 1)
#define DW_IC_CON_10BITADDR_SLAVE BIT(3)
#define DW_IC_CON_10BITADDR_MASTER BIT(4)
#define DW_IC_CON_RESTART_EN BIT(5)
#define DW_IC_CON_SLAVE_DISABLE BIT(6)
#define DW_IC_CON_STOP_DET_IFADDRESSED BIT(7)
#define DW_IC_CON_TX_EMPTY_CTRL BIT(8)
#define DW_IC_CON_RX_FIFO_FULL_HLD_CTRL BIT(9)
/*
* Registers offset
*/
#define DW_IC_CON 0x0
#define DW_IC_TAR 0x4
#define DW_IC_SAR 0x8
#define DW_IC_CON 0x00
#define DW_IC_TAR 0x04
#define DW_IC_SAR 0x08
#define DW_IC_DATA_CMD 0x10
#define DW_IC_SS_SCL_HCNT 0x14
#define DW_IC_SS_SCL_LCNT 0x18
@ -81,19 +81,19 @@
#define DW_IC_COMP_TYPE 0xfc
#define DW_IC_COMP_TYPE_VALUE 0x44570140
#define DW_IC_INTR_RX_UNDER 0x001
#define DW_IC_INTR_RX_OVER 0x002
#define DW_IC_INTR_RX_FULL 0x004
#define DW_IC_INTR_TX_OVER 0x008
#define DW_IC_INTR_TX_EMPTY 0x010
#define DW_IC_INTR_RD_REQ 0x020
#define DW_IC_INTR_TX_ABRT 0x040
#define DW_IC_INTR_RX_DONE 0x080
#define DW_IC_INTR_ACTIVITY 0x100
#define DW_IC_INTR_STOP_DET 0x200
#define DW_IC_INTR_START_DET 0x400
#define DW_IC_INTR_GEN_CALL 0x800
#define DW_IC_INTR_RESTART_DET 0x1000
#define DW_IC_INTR_RX_UNDER BIT(0)
#define DW_IC_INTR_RX_OVER BIT(1)
#define DW_IC_INTR_RX_FULL BIT(2)
#define DW_IC_INTR_TX_OVER BIT(3)
#define DW_IC_INTR_TX_EMPTY BIT(4)
#define DW_IC_INTR_RD_REQ BIT(5)
#define DW_IC_INTR_TX_ABRT BIT(6)
#define DW_IC_INTR_RX_DONE BIT(7)
#define DW_IC_INTR_ACTIVITY BIT(8)
#define DW_IC_INTR_STOP_DET BIT(9)
#define DW_IC_INTR_START_DET BIT(10)
#define DW_IC_INTR_GEN_CALL BIT(11)
#define DW_IC_INTR_RESTART_DET BIT(12)
#define DW_IC_INTR_DEFAULT_MASK (DW_IC_INTR_RX_FULL | \
DW_IC_INTR_TX_ABRT | \
@ -105,13 +105,13 @@
DW_IC_INTR_RX_UNDER | \
DW_IC_INTR_RD_REQ)
#define DW_IC_STATUS_ACTIVITY 0x1
#define DW_IC_STATUS_ACTIVITY BIT(0)
#define DW_IC_STATUS_TFE BIT(2)
#define DW_IC_STATUS_MASTER_ACTIVITY BIT(5)
#define DW_IC_STATUS_SLAVE_ACTIVITY BIT(6)
#define DW_IC_SDA_HOLD_RX_SHIFT 16
#define DW_IC_SDA_HOLD_RX_MASK GENMASK(23, DW_IC_SDA_HOLD_RX_SHIFT)
#define DW_IC_SDA_HOLD_RX_MASK GENMASK(23, 16)
#define DW_IC_ERR_TX_ABRT 0x1
@ -154,20 +154,20 @@
#define ABRT_SLAVE_ARBLOST 14
#define ABRT_SLAVE_RD_INTX 15
#define DW_IC_TX_ABRT_7B_ADDR_NOACK (1UL << ABRT_7B_ADDR_NOACK)
#define DW_IC_TX_ABRT_10ADDR1_NOACK (1UL << ABRT_10ADDR1_NOACK)
#define DW_IC_TX_ABRT_10ADDR2_NOACK (1UL << ABRT_10ADDR2_NOACK)
#define DW_IC_TX_ABRT_TXDATA_NOACK (1UL << ABRT_TXDATA_NOACK)
#define DW_IC_TX_ABRT_GCALL_NOACK (1UL << ABRT_GCALL_NOACK)
#define DW_IC_TX_ABRT_GCALL_READ (1UL << ABRT_GCALL_READ)
#define DW_IC_TX_ABRT_SBYTE_ACKDET (1UL << ABRT_SBYTE_ACKDET)
#define DW_IC_TX_ABRT_SBYTE_NORSTRT (1UL << ABRT_SBYTE_NORSTRT)
#define DW_IC_TX_ABRT_10B_RD_NORSTRT (1UL << ABRT_10B_RD_NORSTRT)
#define DW_IC_TX_ABRT_MASTER_DIS (1UL << ABRT_MASTER_DIS)
#define DW_IC_TX_ARB_LOST (1UL << ARB_LOST)
#define DW_IC_RX_ABRT_SLAVE_RD_INTX (1UL << ABRT_SLAVE_RD_INTX)
#define DW_IC_RX_ABRT_SLAVE_ARBLOST (1UL << ABRT_SLAVE_ARBLOST)
#define DW_IC_RX_ABRT_SLAVE_FLUSH_TXFIFO (1UL << ABRT_SLAVE_FLUSH_TXFIFO)
#define DW_IC_TX_ABRT_7B_ADDR_NOACK BIT(ABRT_7B_ADDR_NOACK)
#define DW_IC_TX_ABRT_10ADDR1_NOACK BIT(ABRT_10ADDR1_NOACK)
#define DW_IC_TX_ABRT_10ADDR2_NOACK BIT(ABRT_10ADDR2_NOACK)
#define DW_IC_TX_ABRT_TXDATA_NOACK BIT(ABRT_TXDATA_NOACK)
#define DW_IC_TX_ABRT_GCALL_NOACK BIT(ABRT_GCALL_NOACK)
#define DW_IC_TX_ABRT_GCALL_READ BIT(ABRT_GCALL_READ)
#define DW_IC_TX_ABRT_SBYTE_ACKDET BIT(ABRT_SBYTE_ACKDET)
#define DW_IC_TX_ABRT_SBYTE_NORSTRT BIT(ABRT_SBYTE_NORSTRT)
#define DW_IC_TX_ABRT_10B_RD_NORSTRT BIT(ABRT_10B_RD_NORSTRT)
#define DW_IC_TX_ABRT_MASTER_DIS BIT(ABRT_MASTER_DIS)
#define DW_IC_TX_ARB_LOST BIT(ARB_LOST)
#define DW_IC_RX_ABRT_SLAVE_RD_INTX BIT(ABRT_SLAVE_RD_INTX)
#define DW_IC_RX_ABRT_SLAVE_ARBLOST BIT(ABRT_SLAVE_ARBLOST)
#define DW_IC_RX_ABRT_SLAVE_FLUSH_TXFIFO BIT(ABRT_SLAVE_FLUSH_TXFIFO)
#define DW_IC_TX_ABRT_NOACK (DW_IC_TX_ABRT_7B_ADDR_NOACK | \
DW_IC_TX_ABRT_10ADDR1_NOACK | \
@ -288,12 +288,12 @@ struct dw_i2c_dev {
bool suspended;
};
#define ACCESS_INTR_MASK 0x00000001
#define ACCESS_NO_IRQ_SUSPEND 0x00000002
#define ACCESS_INTR_MASK BIT(0)
#define ACCESS_NO_IRQ_SUSPEND BIT(1)
#define MODEL_MSCC_OCELOT 0x00000100
#define MODEL_BAIKAL_BT1 0x00000200
#define MODEL_MASK 0x00000f00
#define MODEL_MSCC_OCELOT BIT(8)
#define MODEL_BAIKAL_BT1 BIT(9)
#define MODEL_MASK GENMASK(11, 8)
int i2c_dw_init_regmap(struct dw_i2c_dev *dev);
u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset);

View File

@ -778,11 +778,8 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
init_completion(&i2c->msg_complete);
i2c->irq = ret = platform_get_irq(pdev, 0);
if (ret <= 0) {
dev_err(&pdev->dev, "cannot find HS-I2C IRQ\n");
ret = -EINVAL;
if (ret < 0)
goto err_clk;
}
ret = devm_request_irq(&pdev->dev, i2c->irq, exynos5_i2c_irq,
IRQF_NO_SUSPEND, dev_name(&pdev->dev), i2c);

View File

@ -17,6 +17,7 @@
* Copyright (C) 2008 Darius Augulis <darius.augulis at teltonika.lt>
*
* Copyright 2013 Freescale Semiconductor, Inc.
* Copyright 2020 NXP
*
*/
@ -73,6 +74,11 @@
#define IMX_I2C_I2SR 0x03 /* i2c status */
#define IMX_I2C_I2DR 0x04 /* i2c transfer data */
/*
* All of the layerscape series SoCs support IBIC register.
*/
#define IMX_I2C_IBIC 0x05 /* i2c bus interrupt config */
#define IMX_I2C_REGSHIFT 2
#define VF610_I2C_REGSHIFT 0
@ -91,6 +97,7 @@
#define I2CR_MSTA 0x20
#define I2CR_IIEN 0x40
#define I2CR_IEN 0x80
#define IBIC_BIIE 0x80 /* Bus idle interrupt enable */
/* register bits different operating codes definition:
* 1) I2SR: Interrupt flags clear operation differ between SoCs:
@ -201,6 +208,7 @@ struct imx_i2c_struct {
struct pinctrl_state *pinctrl_pins_gpio;
struct imx_i2c_dma *dma;
struct i2c_client *slave;
};
static const struct imx_i2c_hwdata imx1_i2c_hwdata = {
@ -233,19 +241,6 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {
};
static const struct platform_device_id imx_i2c_devtype[] = {
{
.name = "imx1-i2c",
.driver_data = (kernel_ulong_t)&imx1_i2c_hwdata,
}, {
.name = "imx21-i2c",
.driver_data = (kernel_ulong_t)&imx21_i2c_hwdata,
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(platform, imx_i2c_devtype);
static const struct of_device_id i2c_imx_dt_ids[] = {
{ .compatible = "fsl,imx1-i2c", .data = &imx1_i2c_hwdata, },
{ .compatible = "fsl,imx21-i2c", .data = &imx21_i2c_hwdata, },
@ -265,6 +260,11 @@ static inline int is_imx1_i2c(struct imx_i2c_struct *i2c_imx)
return i2c_imx->hwdata->devtype == IMX1_I2C;
}
static inline int is_vf610_i2c(struct imx_i2c_struct *i2c_imx)
{
return i2c_imx->hwdata->devtype == VF610_I2C;
}
static inline void imx_i2c_write_reg(unsigned int val,
struct imx_i2c_struct *i2c_imx, unsigned int reg)
{
@ -277,6 +277,27 @@ static inline unsigned char imx_i2c_read_reg(struct imx_i2c_struct *i2c_imx,
return readb(i2c_imx->base + (reg << i2c_imx->hwdata->regshift));
}
static void i2c_imx_clear_irq(struct imx_i2c_struct *i2c_imx, unsigned int bits)
{
unsigned int temp;
/*
* i2sr_clr_opcode is the value to clear all interrupts. Here we want to
* clear only <bits>, so we write ~i2sr_clr_opcode with just <bits>
* toggled. This is required because i.MX needs W0C and Vybrid uses W1C.
*/
temp = ~i2c_imx->hwdata->i2sr_clr_opcode ^ bits;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
}
/* Set up i2c controller register and i2c status register to default value. */
static void i2c_imx_reset_regs(struct imx_i2c_struct *i2c_imx)
{
imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
i2c_imx, IMX_I2C_I2CR);
i2c_imx_clear_irq(i2c_imx, I2SR_IIF | I2SR_IAL);
}
/* Functions for DMA support */
static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
dma_addr_t phy_addr)
@ -412,19 +433,6 @@ static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx)
dma->chan_using = NULL;
}
static void i2c_imx_clear_irq(struct imx_i2c_struct *i2c_imx, unsigned int bits)
{
unsigned int temp;
/*
* i2sr_clr_opcode is the value to clear all interrupts. Here we want to
* clear only <bits>, so we write ~i2sr_clr_opcode with just <bits>
* toggled. This is required because i.MX needs W0C and Vybrid uses W1C.
*/
temp = ~i2c_imx->hwdata->i2sr_clr_opcode ^ bits;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
}
static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool atomic)
{
unsigned long orig_jiffies = jiffies;
@ -638,18 +646,165 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx, bool atomic)
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
}
/*
* Enable bus idle interrupts
* Note: IBIC register will be cleared after disabled i2c module.
* All of layerscape series SoCs support IBIC register.
*/
static void i2c_imx_enable_bus_idle(struct imx_i2c_struct *i2c_imx)
{
if (is_vf610_i2c(i2c_imx)) {
unsigned int temp;
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_IBIC);
temp |= IBIC_BIIE;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_IBIC);
}
}
static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx,
unsigned int status, unsigned int ctl)
{
u8 value;
if (status & I2SR_IAL) { /* Arbitration lost */
i2c_imx_clear_irq(i2c_imx, I2SR_IAL);
if (!(status & I2SR_IAAS))
return IRQ_HANDLED;
}
if (status & I2SR_IAAS) { /* Addressed as a slave */
if (status & I2SR_SRW) { /* Master wants to read from us*/
dev_dbg(&i2c_imx->adapter.dev, "read requested");
i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_REQUESTED, &value);
/* Slave transmit */
ctl |= I2CR_MTX;
imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
/* Send data */
imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
} else { /* Master wants to write to us */
dev_dbg(&i2c_imx->adapter.dev, "write requested");
i2c_slave_event(i2c_imx->slave, I2C_SLAVE_WRITE_REQUESTED, &value);
/* Slave receive */
ctl &= ~I2CR_MTX;
imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
/* Dummy read */
imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
}
} else if (!(ctl & I2CR_MTX)) { /* Receive mode */
if (status & I2SR_IBB) { /* No STOP signal detected */
value = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
i2c_slave_event(i2c_imx->slave, I2C_SLAVE_WRITE_RECEIVED, &value);
} else { /* STOP signal is detected */
dev_dbg(&i2c_imx->adapter.dev,
"STOP signal detected");
i2c_slave_event(i2c_imx->slave, I2C_SLAVE_STOP, &value);
}
} else if (!(status & I2SR_RXAK)) { /* Transmit mode received ACK */
ctl |= I2CR_MTX;
imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_PROCESSED, &value);
imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
} else { /* Transmit mode received NAK */
ctl &= ~I2CR_MTX;
imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
}
return IRQ_HANDLED;
}
static void i2c_imx_slave_init(struct imx_i2c_struct *i2c_imx)
{
int temp;
/* Set slave addr. */
imx_i2c_write_reg((i2c_imx->slave->addr << 1), i2c_imx, IMX_I2C_IADR);
i2c_imx_reset_regs(i2c_imx);
/* Enable module */
temp = i2c_imx->hwdata->i2cr_ien_opcode;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
/* Enable interrupt from i2c module */
temp |= I2CR_IIEN;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
i2c_imx_enable_bus_idle(i2c_imx);
}
static int i2c_imx_reg_slave(struct i2c_client *client)
{
struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter);
int ret;
if (i2c_imx->slave)
return -EBUSY;
i2c_imx->slave = client;
/* Resume */
ret = pm_runtime_get_sync(i2c_imx->adapter.dev.parent);
if (ret < 0) {
dev_err(&i2c_imx->adapter.dev, "failed to resume i2c controller");
return ret;
}
i2c_imx_slave_init(i2c_imx);
return 0;
}
static int i2c_imx_unreg_slave(struct i2c_client *client)
{
struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter);
int ret;
if (!i2c_imx->slave)
return -EINVAL;
/* Reset slave address. */
imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IADR);
i2c_imx_reset_regs(i2c_imx);
i2c_imx->slave = NULL;
/* Suspend */
ret = pm_runtime_put_sync(i2c_imx->adapter.dev.parent);
if (ret < 0)
dev_err(&i2c_imx->adapter.dev, "failed to suspend i2c controller");
return ret;
}
static irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx, unsigned int status)
{
/* save status register */
i2c_imx->i2csr = status;
wake_up(&i2c_imx->queue);
return IRQ_HANDLED;
}
static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
{
struct imx_i2c_struct *i2c_imx = dev_id;
unsigned int temp;
unsigned int ctl, status;
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
if (temp & I2SR_IIF) {
/* save status register */
i2c_imx->i2csr = temp;
status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
if (status & I2SR_IIF) {
i2c_imx_clear_irq(i2c_imx, I2SR_IIF);
wake_up(&i2c_imx->queue);
return IRQ_HANDLED;
if (i2c_imx->slave && !(ctl & I2CR_MSTA))
return i2c_imx_slave_isr(i2c_imx, status, ctl);
return i2c_imx_master_isr(i2c_imx, status);
}
return IRQ_NONE;
@ -1027,6 +1182,10 @@ static int i2c_imx_xfer_common(struct i2c_adapter *adapter,
dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__,
(result < 0) ? "error" : "success msg",
(result < 0) ? result : num);
/* After data is transferred, switch to slave mode(as a receiver) */
if (i2c_imx->slave)
i2c_imx_slave_init(i2c_imx);
return (result < 0) ? result : num;
}
@ -1140,6 +1299,8 @@ static const struct i2c_algorithm i2c_imx_algo = {
.master_xfer = i2c_imx_xfer,
.master_xfer_atomic = i2c_imx_xfer_atomic,
.functionality = i2c_imx_func,
.reg_slave = i2c_imx_reg_slave,
.unreg_slave = i2c_imx_unreg_slave,
};
static int i2c_imx_probe(struct platform_device *pdev)
@ -1169,11 +1330,7 @@ static int i2c_imx_probe(struct platform_device *pdev)
return -ENOMEM;
match = device_get_match_data(&pdev->dev);
if (match)
i2c_imx->hwdata = match;
else
i2c_imx->hwdata = (struct imx_i2c_hwdata *)
platform_get_device_id(pdev)->driver_data;
i2c_imx->hwdata = match;
/* Setup i2c_imx driver structure */
strlcpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name));
@ -1233,10 +1390,7 @@ static int i2c_imx_probe(struct platform_device *pdev)
clk_notifier_register(i2c_imx->clk, &i2c_imx->clk_change_nb);
i2c_imx_set_clk(i2c_imx, clk_get_rate(i2c_imx->clk));
/* Set up chip registers to defaults */
imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
i2c_imx, IMX_I2C_I2CR);
imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
i2c_imx_reset_regs(i2c_imx);
/* Init optional bus recovery function */
ret = i2c_imx_init_recovery_info(i2c_imx, pdev);
@ -1344,7 +1498,6 @@ static struct platform_driver i2c_imx_driver = {
.of_match_table = i2c_imx_dt_ids,
.acpi_match_table = i2c_imx_acpi_ids,
},
.id_table = imx_i2c_devtype,
};
static int __init i2c_adap_imx_init(void)

View File

@ -53,7 +53,7 @@
* Features supported by this driver:
* Hardware PEC yes
* Block buffer yes
* Block process call transaction no
* Block process call transaction yes
* Slave mode no
*/
@ -332,7 +332,8 @@ static int ismt_process_desc(const struct ismt_desc *desc,
if (desc->status & ISMT_DESC_SCS) {
if (read_write == I2C_SMBUS_WRITE &&
size != I2C_SMBUS_PROC_CALL)
size != I2C_SMBUS_PROC_CALL &&
size != I2C_SMBUS_BLOCK_PROC_CALL)
return 0;
switch (size) {
@ -345,6 +346,7 @@ static int ismt_process_desc(const struct ismt_desc *desc,
data->word = dma_buffer[0] | (dma_buffer[1] << 8);
break;
case I2C_SMBUS_BLOCK_DATA:
case I2C_SMBUS_BLOCK_PROC_CALL:
if (desc->rxbytes != dma_buffer[0] + 1)
return -EMSGSIZE;
@ -518,6 +520,18 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
}
break;
case I2C_SMBUS_BLOCK_PROC_CALL:
dev_dbg(dev, "I2C_SMBUS_BLOCK_PROC_CALL\n");
dma_size = I2C_SMBUS_BLOCK_MAX;
desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, 1);
desc->wr_len_cmd = data->block[0] + 1;
desc->rd_len = dma_size;
desc->control |= ISMT_DESC_BLK;
dma_direction = DMA_BIDIRECTIONAL;
dma_buffer[0] = command;
memcpy(&dma_buffer[1], &data->block[1], data->block[0]);
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
/* Make sure the length is valid */
if (data->block[0] < 1)
@ -624,6 +638,7 @@ static u32 ismt_func(struct i2c_adapter *adap)
I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_PROC_CALL |
I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
I2C_FUNC_SMBUS_BLOCK_DATA |
I2C_FUNC_SMBUS_I2C_BLOCK |
I2C_FUNC_SMBUS_PEC;

View File

@ -17,6 +17,7 @@
#include <linux/interrupt.h>
#include <linux/mv643xx_i2c.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/reset.h>
#include <linux/io.h>
#include <linux/of.h>
@ -147,6 +148,7 @@ struct mv64xxx_i2c_data {
bool irq_clear_inverted;
/* Clk div is 2 to the power n, not 2 to the power n + 1 */
bool clk_n_base_0;
struct i2c_bus_recovery_info rinfo;
};
static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = {
@ -325,7 +327,8 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
drv_data->msg->flags);
drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
mv64xxx_i2c_hw_init(drv_data);
drv_data->rc = -EIO;
i2c_recover_bus(&drv_data->adapter);
drv_data->rc = -EAGAIN;
}
}
@ -561,6 +564,7 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data)
"time_left: %d\n", drv_data->block,
(int)time_left);
mv64xxx_i2c_hw_init(drv_data);
i2c_recover_bus(&drv_data->adapter);
}
} else
spin_unlock_irqrestore(&drv_data->lock, flags);
@ -870,6 +874,25 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
}
#endif /* CONFIG_OF */
static int mv64xxx_i2c_init_recovery_info(struct mv64xxx_i2c_data *drv_data,
struct device *dev)
{
struct i2c_bus_recovery_info *rinfo = &drv_data->rinfo;
rinfo->pinctrl = devm_pinctrl_get(dev);
if (IS_ERR(rinfo->pinctrl)) {
if (PTR_ERR(rinfo->pinctrl) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_info(dev, "can't get pinctrl, bus recovery not supported\n");
return PTR_ERR(rinfo->pinctrl);
} else if (!rinfo->pinctrl) {
return -ENODEV;
}
drv_data->adapter.bus_recovery_info = rinfo;
return 0;
}
static int
mv64xxx_i2c_probe(struct platform_device *pd)
{
@ -926,6 +949,10 @@ mv64xxx_i2c_probe(struct platform_device *pd)
goto exit_reset;
}
rc = mv64xxx_i2c_init_recovery_info(drv_data, &pd->dev);
if (rc == -EPROBE_DEFER)
goto exit_reset;
drv_data->adapter.dev.parent = &pd->dev;
drv_data->adapter.algo = &mv64xxx_i2c_algo;
drv_data->adapter.owner = THIS_MODULE;

View File

@ -781,28 +781,15 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
return 0;
}
static const struct platform_device_id mxs_i2c_devtype[] = {
{
.name = "imx23-i2c",
.driver_data = MXS_I2C_V1,
}, {
.name = "imx28-i2c",
.driver_data = MXS_I2C_V2,
}, { /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, mxs_i2c_devtype);
static const struct of_device_id mxs_i2c_dt_ids[] = {
{ .compatible = "fsl,imx23-i2c", .data = &mxs_i2c_devtype[0], },
{ .compatible = "fsl,imx28-i2c", .data = &mxs_i2c_devtype[1], },
{ .compatible = "fsl,imx23-i2c", .data = (void *)MXS_I2C_V1, },
{ .compatible = "fsl,imx28-i2c", .data = (void *)MXS_I2C_V2, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mxs_i2c_dt_ids);
static int mxs_i2c_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id =
of_match_device(mxs_i2c_dt_ids, &pdev->dev);
struct device *dev = &pdev->dev;
struct mxs_i2c_dev *i2c;
struct i2c_adapter *adap;
@ -812,10 +799,7 @@ static int mxs_i2c_probe(struct platform_device *pdev)
if (!i2c)
return -ENOMEM;
if (of_id) {
const struct platform_device_id *device_id = of_id->data;
i2c->dev_type = device_id->driver_data;
}
i2c->dev_type = (enum mxs_i2c_devtype)of_device_get_match_data(&pdev->dev);
i2c->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(i2c->regs))

View File

@ -353,15 +353,7 @@ static void gpu_i2c_remove(struct pci_dev *pdev)
pci_free_irq_vectors(pdev);
}
/*
* We need gpu_i2c_suspend() even if it is stub, for runtime pm to work
* correctly. Without it, lspci shows runtime pm status as "D0" for the card.
* Documentation/power/pci.rst also insists for driver to provide this.
*/
static __maybe_unused int gpu_i2c_suspend(struct device *dev)
{
return 0;
}
#define gpu_i2c_suspend NULL
static __maybe_unused int gpu_i2c_resume(struct device *dev)
{

View File

@ -83,7 +83,6 @@ struct ocores_i2c {
#define TYPE_OCORES 0
#define TYPE_GRLIB 1
#define TYPE_SIFIVE_REV0 2
#define OCORES_FLAG_BROKEN_IRQ BIT(1) /* Broken IRQ for FU540-C000 SoC */
@ -476,11 +475,9 @@ static const struct of_device_id ocores_i2c_match[] = {
},
{
.compatible = "sifive,fu540-c000-i2c",
.data = (void *)TYPE_SIFIVE_REV0,
},
{
.compatible = "sifive,i2c0",
.data = (void *)TYPE_SIFIVE_REV0,
},
{},
};
@ -606,7 +603,6 @@ static int ocores_i2c_probe(struct platform_device *pdev)
{
struct ocores_i2c *i2c;
struct ocores_i2c_platform_data *pdata;
const struct of_device_id *match;
struct resource *res;
int irq;
int ret;
@ -686,17 +682,20 @@ static int ocores_i2c_probe(struct platform_device *pdev)
init_waitqueue_head(&i2c->wait);
irq = platform_get_irq(pdev, 0);
irq = platform_get_irq_optional(pdev, 0);
/*
* Since the SoC does have an interrupt, its DT has an interrupt
* property - But this should be bypassed as the IRQ logic in this
* SoC is broken.
*/
if (of_device_is_compatible(pdev->dev.of_node,
"sifive,fu540-c000-i2c")) {
i2c->flags |= OCORES_FLAG_BROKEN_IRQ;
irq = -ENXIO;
}
if (irq == -ENXIO) {
ocores_algorithm.master_xfer = ocores_xfer_polling;
/*
* Set in OCORES_FLAG_BROKEN_IRQ to enable workaround for
* FU540-C000 SoC in polling mode.
*/
match = of_match_node(ocores_i2c_match, pdev->dev.of_node);
if (match && (long)match->data == TYPE_SIFIVE_REV0)
i2c->flags |= OCORES_FLAG_BROKEN_IRQ;
} else {
if (irq < 0)
return irq;

View File

@ -14,6 +14,7 @@
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of_device.h>
@ -76,6 +77,7 @@
#define OWL_I2C_FIFOCTL_TFR BIT(2)
/* I2Cc_FIFOSTAT Bit Mask */
#define OWL_I2C_FIFOSTAT_CECB BIT(0)
#define OWL_I2C_FIFOSTAT_RNB BIT(1)
#define OWL_I2C_FIFOSTAT_RFE BIT(2)
#define OWL_I2C_FIFOSTAT_TFF BIT(5)
@ -83,7 +85,8 @@
#define OWL_I2C_FIFOSTAT_RFD GENMASK(15, 8)
/* I2C bus timeout */
#define OWL_I2C_TIMEOUT msecs_to_jiffies(4 * 1000)
#define OWL_I2C_TIMEOUT_MS (4 * 1000)
#define OWL_I2C_TIMEOUT msecs_to_jiffies(OWL_I2C_TIMEOUT_MS)
#define OWL_I2C_MAX_RETRIES 50
@ -161,14 +164,11 @@ static void owl_i2c_set_freq(struct owl_i2c_dev *i2c_dev)
writel(OWL_I2C_DIV_FACTOR(val), i2c_dev->base + OWL_I2C_REG_CLKDIV);
}
static irqreturn_t owl_i2c_interrupt(int irq, void *_dev)
static void owl_i2c_xfer_data(struct owl_i2c_dev *i2c_dev)
{
struct owl_i2c_dev *i2c_dev = _dev;
struct i2c_msg *msg = i2c_dev->msg;
unsigned int stat, fifostat;
spin_lock(&i2c_dev->lock);
i2c_dev->err = 0;
/* Handle NACK from slave */
@ -178,7 +178,7 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev)
/* Clear NACK error bit by writing "1" */
owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOSTAT,
OWL_I2C_FIFOSTAT_RNB, true);
goto stop;
return;
}
/* Handle bus error */
@ -188,7 +188,7 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev)
/* Clear BUS error bit by writing "1" */
owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_STAT,
OWL_I2C_STAT_BEB, true);
goto stop;
return;
}
/* Handle FIFO read */
@ -206,8 +206,16 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev)
i2c_dev->base + OWL_I2C_REG_TXDAT);
}
}
}
static irqreturn_t owl_i2c_interrupt(int irq, void *_dev)
{
struct owl_i2c_dev *i2c_dev = _dev;
spin_lock(&i2c_dev->lock);
owl_i2c_xfer_data(i2c_dev);
stop:
/* Clear pending interrupts */
owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_STAT,
OWL_I2C_STAT_IRQP, true);
@ -240,8 +248,8 @@ static int owl_i2c_check_bus_busy(struct i2c_adapter *adap)
return 0;
}
static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num)
static int owl_i2c_xfer_common(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num, bool atomic)
{
struct owl_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
struct i2c_msg *msg;
@ -285,11 +293,12 @@ static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
goto err_exit;
}
reinit_completion(&i2c_dev->msg_complete);
if (!atomic)
reinit_completion(&i2c_dev->msg_complete);
/* Enable I2C controller interrupt */
/* Enable/disable I2C controller interrupt */
owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
OWL_I2C_CTL_IRQE, true);
OWL_I2C_CTL_IRQE, !atomic);
/*
* Select: FIFO enable, Master mode, Stop enable, Data count enable,
@ -357,20 +366,33 @@ static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
spin_unlock_irqrestore(&i2c_dev->lock, flags);
time_left = wait_for_completion_timeout(&i2c_dev->msg_complete,
adap->timeout);
if (atomic) {
/* Wait for Command Execute Completed or NACK Error bits */
ret = readl_poll_timeout_atomic(i2c_dev->base + OWL_I2C_REG_FIFOSTAT,
val, val & (OWL_I2C_FIFOSTAT_CECB |
OWL_I2C_FIFOSTAT_RNB),
10, OWL_I2C_TIMEOUT_MS * 1000);
} else {
time_left = wait_for_completion_timeout(&i2c_dev->msg_complete,
adap->timeout);
if (!time_left)
ret = -ETIMEDOUT;
}
spin_lock_irqsave(&i2c_dev->lock, flags);
if (time_left == 0) {
if (ret) {
dev_err(&adap->dev, "Transaction timed out\n");
/* Send stop condition and release the bus */
owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
OWL_I2C_CTL_GBCC_STOP | OWL_I2C_CTL_RB,
true);
ret = -ETIMEDOUT;
goto err_exit;
}
if (atomic)
owl_i2c_xfer_data(i2c_dev);
ret = i2c_dev->err < 0 ? i2c_dev->err : num;
err_exit:
@ -384,9 +406,22 @@ static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
return ret;
}
static int owl_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num)
{
return owl_i2c_xfer_common(adap, msgs, num, false);
}
static int owl_i2c_xfer_atomic(struct i2c_adapter *adap,
struct i2c_msg *msgs, int num)
{
return owl_i2c_xfer_common(adap, msgs, num, true);
}
static const struct i2c_algorithm owl_i2c_algorithm = {
.master_xfer = owl_i2c_master_xfer,
.functionality = owl_i2c_func,
.master_xfer = owl_i2c_xfer,
.master_xfer_atomic = owl_i2c_xfer_atomic,
.functionality = owl_i2c_func,
};
static const struct i2c_adapter_quirks owl_i2c_quirks = {
@ -473,6 +508,7 @@ static int owl_i2c_probe(struct platform_device *pdev)
}
static const struct of_device_id owl_i2c_of_match[] = {
{ .compatible = "actions,s500-i2c" },
{ .compatible = "actions,s700-i2c" },
{ .compatible = "actions,s900-i2c" },
{ /* sentinel */ }
@ -484,6 +520,7 @@ static struct platform_driver owl_i2c_driver = {
.driver = {
.name = "owl-i2c",
.of_match_table = of_match_ptr(owl_i2c_of_match),
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
};
module_platform_driver(owl_i2c_driver);

View File

@ -33,8 +33,6 @@ struct i2c_pca_pf_data {
wait_queue_head_t wait;
struct i2c_adapter adap;
struct i2c_algo_pca_data algo_data;
unsigned long io_base;
unsigned long io_size;
};
/* Read/Write functions for different register alignments */
@ -156,8 +154,6 @@ static int i2c_pca_pf_probe(struct platform_device *pdev)
init_waitqueue_head(&i2c->wait);
i2c->io_base = res->start;
i2c->io_size = resource_size(res);
i2c->irq = irq;
i2c->adap.nr = pdev->id;

View File

@ -264,9 +264,6 @@ struct pxa_i2c {
u32 hs_mask;
struct i2c_bus_recovery_info recovery;
struct pinctrl *pinctrl;
struct pinctrl_state *pinctrl_default;
struct pinctrl_state *pinctrl_recovery;
};
#define _IBMR(i2c) ((i2c)->reg_ibmr)
@ -1305,13 +1302,12 @@ static void i2c_pxa_prepare_recovery(struct i2c_adapter *adap)
*/
gpiod_set_value(i2c->recovery.scl_gpiod, ibmr & IBMR_SCLS);
gpiod_set_value(i2c->recovery.sda_gpiod, ibmr & IBMR_SDAS);
WARN_ON(pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_recovery));
}
static void i2c_pxa_unprepare_recovery(struct i2c_adapter *adap)
{
struct pxa_i2c *i2c = adap->algo_data;
struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
u32 isr;
/*
@ -1325,7 +1321,7 @@ static void i2c_pxa_unprepare_recovery(struct i2c_adapter *adap)
i2c_pxa_do_reset(i2c);
}
WARN_ON(pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_default));
WARN_ON(pinctrl_select_state(bri->pinctrl, bri->pins_default));
dev_dbg(&i2c->adap.dev, "recovery: IBMR 0x%08x ISR 0x%08x\n",
readl(_IBMR(i2c)), readl(_ISR(i2c)));
@ -1347,76 +1343,20 @@ static int i2c_pxa_init_recovery(struct pxa_i2c *i2c)
if (IS_ENABLED(CONFIG_I2C_PXA_SLAVE))
return 0;
i2c->pinctrl = devm_pinctrl_get(dev);
if (PTR_ERR(i2c->pinctrl) == -ENODEV)
i2c->pinctrl = NULL;
if (IS_ERR(i2c->pinctrl))
return PTR_ERR(i2c->pinctrl);
if (!i2c->pinctrl)
return 0;
i2c->pinctrl_default = pinctrl_lookup_state(i2c->pinctrl,
PINCTRL_STATE_DEFAULT);
i2c->pinctrl_recovery = pinctrl_lookup_state(i2c->pinctrl, "recovery");
if (IS_ERR(i2c->pinctrl_default) || IS_ERR(i2c->pinctrl_recovery)) {
dev_info(dev, "missing pinmux recovery information: %ld %ld\n",
PTR_ERR(i2c->pinctrl_default),
PTR_ERR(i2c->pinctrl_recovery));
return 0;
}
/*
* Claiming GPIOs can influence the pinmux state, and may glitch the
* I2C bus. Do this carefully.
*/
bri->scl_gpiod = devm_gpiod_get(dev, "scl", GPIOD_OUT_HIGH_OPEN_DRAIN);
if (bri->scl_gpiod == ERR_PTR(-EPROBE_DEFER))
return -EPROBE_DEFER;
if (IS_ERR(bri->scl_gpiod)) {
dev_info(dev, "missing scl gpio recovery information: %pe\n",
bri->scl_gpiod);
return 0;
}
/*
* We have SCL. Pull SCL low and wait a bit so that SDA glitches
* have no effect.
*/
gpiod_direction_output(bri->scl_gpiod, 0);
udelay(10);
bri->sda_gpiod = devm_gpiod_get(dev, "sda", GPIOD_OUT_HIGH_OPEN_DRAIN);
/* Wait a bit in case of a SDA glitch, and then release SCL. */
udelay(10);
gpiod_direction_output(bri->scl_gpiod, 1);
if (bri->sda_gpiod == ERR_PTR(-EPROBE_DEFER))
return -EPROBE_DEFER;
if (IS_ERR(bri->sda_gpiod)) {
dev_info(dev, "missing sda gpio recovery information: %pe\n",
bri->sda_gpiod);
bri->pinctrl = devm_pinctrl_get(dev);
if (PTR_ERR(bri->pinctrl) == -ENODEV) {
bri->pinctrl = NULL;
return 0;
}
if (IS_ERR(bri->pinctrl))
return PTR_ERR(bri->pinctrl);
bri->prepare_recovery = i2c_pxa_prepare_recovery;
bri->unprepare_recovery = i2c_pxa_unprepare_recovery;
bri->recover_bus = i2c_generic_scl_recovery;
i2c->adap.bus_recovery_info = bri;
/*
* Claiming GPIOs can change the pinmux state, which confuses the
* pinctrl since pinctrl's idea of the current setting is unaffected
* by the pinmux change caused by claiming the GPIO. Work around that
* by switching pinctrl to the GPIO state here. We do it this way to
* avoid glitching the I2C bus.
*/
pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_recovery);
return pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_default);
return 0;
}
static int i2c_pxa_probe(struct platform_device *dev)

View File

@ -353,19 +353,18 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
{
dma_addr_t rx_dma;
unsigned long time_left;
void *dma_buf = NULL;
void *dma_buf;
struct geni_se *se = &gi2c->se;
size_t len = msg->len;
if (!of_machine_is_compatible("lenovo,yoga-c630"))
dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);
dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);
if (dma_buf)
geni_se_select_mode(se, GENI_SE_DMA);
else
geni_se_select_mode(se, GENI_SE_FIFO);
writel_relaxed(len, se->base + SE_I2C_RX_TRANS_LEN);
geni_se_setup_m_cmd(se, I2C_READ, m_param);
if (dma_buf && geni_se_rx_dma_prep(se, dma_buf, len, &rx_dma)) {
geni_se_select_mode(se, GENI_SE_FIFO);
@ -373,8 +372,6 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
dma_buf = NULL;
}
geni_se_setup_m_cmd(se, I2C_READ, m_param);
time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT);
if (!time_left)
geni_i2c_abort_xfer(gi2c);
@ -395,19 +392,18 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
{
dma_addr_t tx_dma;
unsigned long time_left;
void *dma_buf = NULL;
void *dma_buf;
struct geni_se *se = &gi2c->se;
size_t len = msg->len;
if (!of_machine_is_compatible("lenovo,yoga-c630"))
dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);
dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);
if (dma_buf)
geni_se_select_mode(se, GENI_SE_DMA);
else
geni_se_select_mode(se, GENI_SE_FIFO);
writel_relaxed(len, se->base + SE_I2C_TX_TRANS_LEN);
geni_se_setup_m_cmd(se, I2C_WRITE, m_param);
if (dma_buf && geni_se_tx_dma_prep(se, dma_buf, len, &tx_dma)) {
geni_se_select_mode(se, GENI_SE_FIFO);
@ -415,8 +411,6 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
dma_buf = NULL;
}
geni_se_setup_m_cmd(se, I2C_WRITE, m_param);
if (!dma_buf) /* Get FIFO IRQ */
writel_relaxed(1, se->base + SE_GENI_TX_WATERMARK_REG);

View File

@ -956,10 +956,38 @@ static int sh_mobile_i2c_remove(struct platform_device *dev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int sh_mobile_i2c_suspend(struct device *dev)
{
struct sh_mobile_i2c_data *pd = dev_get_drvdata(dev);
i2c_mark_adapter_suspended(&pd->adap);
return 0;
}
static int sh_mobile_i2c_resume(struct device *dev)
{
struct sh_mobile_i2c_data *pd = dev_get_drvdata(dev);
i2c_mark_adapter_resumed(&pd->adap);
return 0;
}
static const struct dev_pm_ops sh_mobile_i2c_pm_ops = {
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sh_mobile_i2c_suspend,
sh_mobile_i2c_resume)
};
#define DEV_PM_OPS (&sh_mobile_i2c_pm_ops)
#else
#define DEV_PM_OPS NULL
#endif /* CONFIG_PM_SLEEP */
static struct platform_driver sh_mobile_i2c_driver = {
.driver = {
.name = "i2c-sh_mobile",
.of_match_table = sh_mobile_i2c_dt_ids,
.pm = DEV_PM_OPS,
},
.probe = sh_mobile_i2c_probe,
.remove = sh_mobile_i2c_remove,

View File

@ -549,17 +549,18 @@ static int i2c_device_probe(struct device *dev)
static int i2c_device_remove(struct device *dev)
{
struct i2c_client *client = i2c_verify_client(dev);
struct i2c_client *client = to_i2c_client(dev);
struct i2c_driver *driver;
int status = 0;
if (!client || !dev->driver)
return 0;
driver = to_i2c_driver(dev->driver);
if (driver->remove) {
int status;
dev_dbg(dev, "remove\n");
status = driver->remove(client);
if (status)
dev_warn(dev, "remove failed (%pe), will be ignored\n", ERR_PTR(status));
}
dev_pm_domain_detach(&client->dev, true);
@ -571,7 +572,8 @@ static int i2c_device_remove(struct device *dev)
if (client->flags & I2C_CLIENT_HOST_NOTIFY)
pm_runtime_put(&client->adapter->dev);
return status;
/* return always 0 because there is WIP to make remove-functions void */
return 0;
}
static void i2c_device_shutdown(struct device *dev)

View File

@ -468,7 +468,6 @@ static void memstick_check(struct work_struct *work)
host->card = card;
if (device_register(&card->dev)) {
put_device(&card->dev);
kfree(host->card);
host->card = NULL;
}
} else

View File

@ -276,7 +276,7 @@ static const char *mspro_block_attr_name(unsigned char tag)
return "attr_devinfo";
default:
return NULL;
};
}
}
typedef ssize_t (*sysfs_show_t)(struct device *dev,

View File

@ -748,7 +748,7 @@ static int jmb38x_ms_set_param(struct memstick_host *msh,
clock_delay);
host->ifmode = value;
break;
};
}
return 0;
}

View File

@ -759,8 +759,10 @@ static int r592_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto error3;
dev->mmio = pci_ioremap_bar(pdev, 0);
if (!dev->mmio)
if (!dev->mmio) {
error = -ENOMEM;
goto error4;
}
dev->irq = pdev->irq;
spin_lock_init(&dev->irq_lock);
@ -786,12 +788,14 @@ static int r592_probe(struct pci_dev *pdev, const struct pci_device_id *id)
&dev->dummy_dma_page_physical_address, GFP_KERNEL);
r592_stop_dma(dev , 0);
if (request_irq(dev->irq, &r592_irq, IRQF_SHARED,
DRV_NAME, dev))
error = request_irq(dev->irq, &r592_irq, IRQF_SHARED,
DRV_NAME, dev);
if (error)
goto error6;
r592_update_card_detect(dev);
if (memstick_add_host(host))
error = memstick_add_host(host);
if (error)
goto error7;
message("driver successfully loaded");

View File

@ -528,7 +528,7 @@ static int tifm_ms_set_param(struct memstick_host *msh,
} else
return -EINVAL;
break;
};
}
return 0;
}

View File

@ -26,16 +26,16 @@ static u8 rts5261_get_ic_version(struct rtsx_pcr *pcr)
static void rts5261_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
{
u8 driving_3v3[4][3] = {
{0x13, 0x13, 0x13},
{0x96, 0x96, 0x96},
{0x96, 0x96, 0x96},
{0x7F, 0x7F, 0x7F},
{0x96, 0x96, 0x96},
{0x13, 0x13, 0x13},
};
u8 driving_1v8[4][3] = {
{0x99, 0x99, 0x99},
{0xB3, 0xB3, 0xB3},
{0x3A, 0x3A, 0x3A},
{0xE6, 0xE6, 0xE6},
{0xB3, 0xB3, 0xB3},
{0x99, 0x99, 0x99},
};
u8 (*driving)[3], drive_sel;
@ -67,12 +67,17 @@ static void rtsx5261_fetch_vendor_settings(struct rtsx_pcr *pcr)
pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
if (!rts5261_vendor_setting_valid(reg)) {
/* Not support MMC default */
pcr->extra_caps |= EXTRA_CAPS_NO_MMC;
pcr_dbg(pcr, "skip fetch vendor setting\n");
return;
}
pcr->card_drive_sel &= 0x3F;
pcr->card_drive_sel |= rts5261_reg_to_card_drive_sel(reg);
if (!rts5261_reg_check_mmc_support(reg))
pcr->extra_caps |= EXTRA_CAPS_NO_MMC;
/* TO do: need to add rtd3 function */
pcr->rtd3_en = rts5261_reg_to_rtd3(reg);
if (rts5261_reg_check_reverse_socket(reg))
pcr->flags |= PCR_REVERSE_SOCKET;
@ -171,6 +176,8 @@ static int rts5261_card_power_on(struct rtsx_pcr *pcr, int card)
if (option->ocp_en)
rtsx_pci_enable_ocp(pcr);
rtsx_pci_write_register(pcr, REG_CRC_DUMMY_0,
CFG_SD_POW_AUTO_PD, CFG_SD_POW_AUTO_PD);
rtsx_pci_write_register(pcr, RTS5261_LDO1_CFG1,
RTS5261_LDO1_TUNE_MASK, RTS5261_LDO1_33);
@ -272,6 +279,9 @@ static void rts5261_enable_ocp(struct rtsx_pcr *pcr)
u8 val = 0;
val = SD_OCP_INT_EN | SD_DETECT_EN;
rtsx_pci_write_register(pcr, RTS5261_LDO1_CFG0,
RTS5261_LDO1_OCP_EN | RTS5261_LDO1_OCP_LMT_EN,
RTS5261_LDO1_OCP_EN | RTS5261_LDO1_OCP_LMT_EN);
rtsx_pci_write_register(pcr, REG_OCPCTL, 0xFF, val);
}
@ -295,6 +305,8 @@ static int rts5261_card_power_off(struct rtsx_pcr *pcr, int card)
err = rtsx_pci_write_register(pcr, RTS5261_LDO1233318_POW_CTL,
RTS5261_LDO_POWERON_MASK, 0);
rtsx_pci_write_register(pcr, REG_CRC_DUMMY_0,
CFG_SD_POW_AUTO_PD, 0);
if (pcr->option.ocp_en)
rtsx_pci_disable_ocp(pcr);
@ -340,7 +352,7 @@ static void rts5261_clear_ocpstat(struct rtsx_pcr *pcr)
rtsx_pci_write_register(pcr, REG_OCPCTL, mask, val);
udelay(10);
udelay(1000);
rtsx_pci_write_register(pcr, REG_OCPCTL, mask, 0);
}
@ -353,9 +365,9 @@ static void rts5261_process_ocp(struct rtsx_pcr *pcr)
rtsx_pci_get_ocpstat(pcr, &pcr->ocp_stat);
if (pcr->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
rts5261_clear_ocpstat(pcr);
rts5261_card_power_off(pcr, RTSX_SD_CARD);
rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, 0);
rts5261_clear_ocpstat(pcr);
pcr->ocp_stat = 0;
}
@ -467,6 +479,7 @@ static void rts5261_init_from_cfg(struct rtsx_pcr *pcr)
static int rts5261_extra_init_hw(struct rtsx_pcr *pcr)
{
struct rtsx_cr_option *option = &pcr->option;
u32 val;
rtsx_pci_write_register(pcr, RTS5261_AUTOLOAD_CFG1,
CD_RESUME_EN_MASK, CD_RESUME_EN_MASK);
@ -481,6 +494,10 @@ static int rts5261_extra_init_hw(struct rtsx_pcr *pcr)
AUX_CLK_ACTIVE_SEL_MASK, MAC_CKSW_DONE);
rtsx_pci_write_register(pcr, L1SUB_CONFIG3, 0xFF, 0);
if (is_version_higher_than(pcr, PID_5261, IC_VER_B)) {
val = rtsx_pci_readl(pcr, RTSX_DUM_REG);
rtsx_pci_writel(pcr, RTSX_DUM_REG, val | 0x1);
}
rtsx_pci_write_register(pcr, RTS5261_AUTOLOAD_CFG4,
RTS5261_AUX_CLK_16M_EN, 0);
@ -502,6 +519,11 @@ static int rts5261_extra_init_hw(struct rtsx_pcr *pcr)
/* Configure driving */
rts5261_fill_driving(pcr, OUTPUT_3V3);
if (pcr->flags & PCR_REVERSE_SOCKET)
rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x30);
else
rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x00);
/*
* If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced
* to drive low, and we forcibly request clock.
@ -513,6 +535,7 @@ static int rts5261_extra_init_hw(struct rtsx_pcr *pcr)
rtsx_pci_write_register(pcr, PETXCFG,
FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);
rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB);
rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x10, 0x00);
rtsx_pci_write_register(pcr, RTS5261_REG_PME_FORCE_CTL,
FORCE_PM_CONTROL | FORCE_PM_VALUE, FORCE_PM_CONTROL);
@ -526,22 +549,30 @@ static int rts5261_extra_init_hw(struct rtsx_pcr *pcr)
static void rts5261_enable_aspm(struct rtsx_pcr *pcr, bool enable)
{
u8 val = FORCE_ASPM_CTL0 | FORCE_ASPM_CTL1;
u8 mask = FORCE_ASPM_VAL_MASK | FORCE_ASPM_CTL0 | FORCE_ASPM_CTL1;
if (pcr->aspm_enabled == enable)
return;
val |= (pcr->aspm_en & 0x02);
rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, mask, val);
pcie_capability_clear_and_set_word(pcr->pci, PCI_EXP_LNKCTL,
PCI_EXP_LNKCTL_ASPMC, pcr->aspm_en);
pcr->aspm_enabled = enable;
}
static void rts5261_disable_aspm(struct rtsx_pcr *pcr, bool enable)
{
u8 val = FORCE_ASPM_CTL0 | FORCE_ASPM_CTL1;
u8 mask = FORCE_ASPM_VAL_MASK | FORCE_ASPM_CTL0 | FORCE_ASPM_CTL1;
if (pcr->aspm_enabled == enable)
return;
pcie_capability_clear_and_set_word(pcr->pci, PCI_EXP_LNKCTL,
PCI_EXP_LNKCTL_ASPMC, 0);
rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, mask, val);
rtsx_pci_write_register(pcr, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0);
udelay(10);
pcr->aspm_enabled = enable;
@ -618,7 +649,7 @@ int rts5261_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
if (initial_mode) {
/* We use 250k(around) here, in initial stage */
if (is_version(pcr, PID_5261, IC_VER_D)) {
if (is_version_higher_than(pcr, PID_5261, IC_VER_C)) {
clk_divider = SD_CLK_DIVIDE_256;
card_clock = 60000000;
} else {
@ -669,7 +700,7 @@ int rts5261_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
div++;
}
n = (n / 2);
n = (n / 2) - 1;
pcr_dbg(pcr, "n = %d, div = %d\n", n, div);
ssc_depth = depth[ssc_depth];
@ -738,15 +769,19 @@ void rts5261_init_params(struct rtsx_pcr *pcr)
{
struct rtsx_cr_option *option = &pcr->option;
struct rtsx_hw_param *hw_param = &pcr->hw_param;
u8 val;
pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
rtsx_pci_read_register(pcr, RTS5261_FW_STATUS, &val);
if (!(val & RTS5261_EXPRESS_LINK_FAIL_MASK))
pcr->extra_caps |= EXTRA_CAPS_SD_EXPRESS;
pcr->num_slots = 1;
pcr->ops = &rts5261_pcr_ops;
pcr->flags = 0;
pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT;
pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B;
pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B;
pcr->sd30_drive_sel_1v8 = 0x00;
pcr->sd30_drive_sel_3v3 = 0x00;
pcr->aspm_en = ASPM_L1_EN;
pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 11);
pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5);

View File

@ -12,12 +12,13 @@
/*New add*/
#define rts5261_vendor_setting_valid(reg) ((reg) & 0x010000)
#define rts5261_reg_to_aspm(reg) (((reg) >> 28) ^ 0x03)
#define rts5261_reg_to_aspm(reg) \
(((~(reg) >> 28) & 0x02) | (((reg) >> 28) & 0x01))
#define rts5261_reg_check_reverse_socket(reg) ((reg) & 0x04)
#define rts5261_reg_to_card_drive_sel(reg) ((((reg) >> 6) & 0x01) << 6)
#define rts5261_reg_to_sd30_drive_sel_1v8(reg) (((reg) >> 22) ^ 0x03)
#define rts5261_reg_to_sd30_drive_sel_3v3(reg) (((reg) >> 16) ^ 0x03)
#define rts5261_reg_to_sd30_drive_sel_1v8(reg) (((reg) >> 22) & 0x03)
#define rts5261_reg_to_sd30_drive_sel_3v3(reg) (((reg) >> 16) & 0x03)
#define rts5261_reg_to_rtd3(reg) ((reg) & 0x08)
#define rts5261_reg_check_mmc_support(reg) ((reg) & 0x10)
#define RTS5261_AUTOLOAD_CFG0 0xFF7B
#define RTS5261_AUTOLOAD_CFG1 0xFF7C
@ -60,28 +61,6 @@
/* DMACTL 0xFE2C */
#define RTS5261_DMA_PACK_SIZE_MASK 0xF0
/* FW config info register */
#define RTS5261_FW_CFG_INFO0 0xFF50
#define RTS5261_FW_EXPRESS_TEST_MASK (0x01<<0)
#define RTS5261_FW_EA_MODE_MASK (0x01<<5)
/* FW config register */
#define RTS5261_FW_CFG0 0xFF54
#define RTS5261_FW_ENTER_EXPRESS (0x01<<0)
#define RTS5261_FW_CFG1 0xFF55
#define RTS5261_SYS_CLK_SEL_MCU_CLK (0x01<<7)
#define RTS5261_CRC_CLK_SEL_MCU_CLK (0x01<<6)
#define RTS5261_FAKE_MCU_CLOCK_GATING (0x01<<5)
/*MCU_bus_mode_sel: 0=real 8051 1=fake mcu*/
#define RTS5261_MCU_BUS_SEL_MASK (0x01<<4)
/*MCU_clock_sel:VerA 00=aux16M 01=aux400K 1x=REFCLK100M*/
/*MCU_clock_sel:VerB 00=aux400K 01=aux16M 10=REFCLK100M*/
#define RTS5261_MCU_CLOCK_SEL_MASK (0x03<<2)
#define RTS5261_MCU_CLOCK_SEL_16M (0x01<<2)
#define RTS5261_MCU_CLOCK_GATING (0x01<<1)
#define RTS5261_DRIVER_ENABLE_FW (0x01<<0)
/* FW status register */
#define RTS5261_FW_STATUS 0xFF56
#define RTS5261_EXPRESS_LINK_FAIL_MASK (0x01<<7)
@ -121,12 +100,6 @@
#define RTS5261_DV3318_19 (0x04<<4)
#define RTS5261_DV3318_33 (0x07<<4)
#define RTS5261_LDO1_CFG0 0xFF72
#define RTS5261_LDO1_OCP_THD_MASK (0x07<<5)
#define RTS5261_LDO1_OCP_EN (0x01<<4)
#define RTS5261_LDO1_OCP_LMT_THD_MASK (0x03<<2)
#define RTS5261_LDO1_OCP_LMT_EN (0x01<<1)
/* CRD6603-433 190319 request changed */
#define RTS5261_LDO1_OCP_THD_740 (0x00<<5)
#define RTS5261_LDO1_OCP_THD_800 (0x01<<5)

View File

@ -1004,6 +1004,11 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id)
} else {
pcr->card_removed |= SD_EXIST;
pcr->card_inserted &= ~SD_EXIST;
if (PCI_PID(pcr) == PID_5261) {
rtsx_pci_write_register(pcr, RTS5261_FW_STATUS,
RTS5261_EXPRESS_LINK_FAIL_MASK, 0);
pcr->extra_caps |= EXTRA_CAPS_SD_EXPRESS;
}
}
pcr->dma_error_count = 0;
}

View File

@ -2147,8 +2147,12 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
mmc_go_idle(host);
if (!(host->caps2 & MMC_CAP2_NO_SD))
mmc_send_if_cond(host, host->ocr_avail);
if (!(host->caps2 & MMC_CAP2_NO_SD)) {
if (mmc_send_if_cond_pcie(host, host->ocr_avail))
goto out;
if (mmc_card_sd_express(host))
return 0;
}
/* Order's important: probe SDIO, then SD, then MMC */
if (!(host->caps2 & MMC_CAP2_NO_SDIO))
@ -2163,6 +2167,7 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
if (!mmc_attach_mmc(host))
return 0;
out:
mmc_power_off(host);
return -EIO;
}
@ -2290,6 +2295,12 @@ void mmc_rescan(struct work_struct *work)
goto out;
}
/* If an SD express card is present, then leave it as is. */
if (mmc_card_sd_express(host)) {
mmc_release_host(host);
goto out;
}
for (i = 0; i < ARRAY_SIZE(freqs); i++) {
unsigned int freq = freqs[i];
if (freq > host->f_max) {

View File

@ -77,5 +77,11 @@ static inline bool mmc_card_hs400es(struct mmc_card *card)
return card->host->ios.enhanced_strobe;
}
static inline bool mmc_card_sd_express(struct mmc_host *host)
{
return host->ios.timing == MMC_TIMING_SD_EXP ||
host->ios.timing == MMC_TIMING_SD_EXP_1_2V;
}
#endif

View File

@ -158,7 +158,8 @@ int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
return err;
}
int mmc_send_if_cond(struct mmc_host *host, u32 ocr)
static int __mmc_send_if_cond(struct mmc_host *host, u32 ocr, u8 pcie_bits,
u32 *resp)
{
struct mmc_command cmd = {};
int err;
@ -171,7 +172,7 @@ int mmc_send_if_cond(struct mmc_host *host, u32 ocr)
* SD 1.0 cards.
*/
cmd.opcode = SD_SEND_IF_COND;
cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern;
cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | pcie_bits << 8 | test_pattern;
cmd.flags = MMC_RSP_SPI_R7 | MMC_RSP_R7 | MMC_CMD_BCR;
err = mmc_wait_for_cmd(host, &cmd, 0);
@ -186,6 +187,50 @@ int mmc_send_if_cond(struct mmc_host *host, u32 ocr)
if (result_pattern != test_pattern)
return -EIO;
if (resp)
*resp = cmd.resp[0];
return 0;
}
int mmc_send_if_cond(struct mmc_host *host, u32 ocr)
{
return __mmc_send_if_cond(host, ocr, 0, NULL);
}
int mmc_send_if_cond_pcie(struct mmc_host *host, u32 ocr)
{
u32 resp = 0;
u8 pcie_bits = 0;
int ret;
if (host->caps2 & MMC_CAP2_SD_EXP) {
/* Probe card for SD express support via PCIe. */
pcie_bits = 0x10;
if (host->caps2 & MMC_CAP2_SD_EXP_1_2V)
/* Probe also for 1.2V support. */
pcie_bits = 0x30;
}
ret = __mmc_send_if_cond(host, ocr, pcie_bits, &resp);
if (ret)
return 0;
/* Continue with the SD express init, if the card supports it. */
resp &= 0x3000;
if (pcie_bits && resp) {
if (resp == 0x3000)
host->ios.timing = MMC_TIMING_SD_EXP_1_2V;
else
host->ios.timing = MMC_TIMING_SD_EXP;
/*
* According to the spec the clock shall also be gated, but
* let's leave this to the host driver for more flexibility.
*/
return host->ops->init_sd_express(host, &host->ios);
}
return 0;
}

View File

@ -16,6 +16,7 @@ struct mmc_host;
int mmc_app_set_bus_width(struct mmc_card *card, int width);
int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
int mmc_send_if_cond(struct mmc_host *host, u32 ocr);
int mmc_send_if_cond_pcie(struct mmc_host *host, u32 ocr);
int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca);
int mmc_app_send_scr(struct mmc_card *card);
int mmc_sd_switch(struct mmc_card *card, int mode, int group,

View File

@ -631,8 +631,8 @@ config MMC_SPI
config MMC_S3C
tristate "Samsung S3C SD/MMC Card Interface support"
depends on ARCH_S3C24XX
depends on S3C24XX_DMAC
depends on ARCH_S3C24XX || COMPILE_TEST
depends on S3C24XX_DMAC || COMPILE_TEST
help
This selects a driver for the MCI interface found in
Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs.
@ -664,7 +664,7 @@ config MMC_S3C_PIO
config MMC_S3C_DMA
bool "Use DMA transfers only"
help
Use DMA to transfer data between memory and the hardare.
Use DMA to transfer data between memory and the hardware.
Currently, the DMA support in this driver seems to not be
working properly and needs to be debugged before this
@ -1023,6 +1023,7 @@ config MMC_BCM2835
config MMC_MTK
tristate "MediaTek SD/MMC Card Interface support"
depends on HAS_DMA
depends on COMMON_CLK
select REGULATOR
select MMC_CQHCI
help

View File

@ -290,7 +290,7 @@ static void mmc_davinci_start_command(struct mmc_davinci_host *host,
default:
s = ", (R? response)";
break;
}; s; }));
} s; }));
host->cmd = cmd;
switch (mmc_resp_type(cmd)) {

View File

@ -2617,7 +2617,6 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
struct dw_mci *host = dev_id;
u32 pending;
struct dw_mci_slot *slot = host->slot;
unsigned long irqflags;
pending = mci_readl(host, MINTSTS); /* read-only mask reg */
@ -2632,15 +2631,15 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
* Hold the lock; we know cmd11_timer can't be kicked
* off after the lock is released, so safe to delete.
*/
spin_lock_irqsave(&host->irq_lock, irqflags);
spin_lock(&host->irq_lock);
dw_mci_cmd_interrupt(host, pending);
spin_unlock_irqrestore(&host->irq_lock, irqflags);
spin_unlock(&host->irq_lock);
del_timer(&host->cmd11_timer);
}
if (pending & DW_MCI_CMD_ERROR_FLAGS) {
spin_lock_irqsave(&host->irq_lock, irqflags);
spin_lock(&host->irq_lock);
del_timer(&host->cto_timer);
mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS);
@ -2648,7 +2647,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
smp_wmb(); /* drain writebuffer */
set_bit(EVENT_CMD_COMPLETE, &host->pending_events);
spin_unlock_irqrestore(&host->irq_lock, irqflags);
spin_unlock(&host->irq_lock);
}
if (pending & DW_MCI_DATA_ERROR_FLAGS) {
@ -2661,7 +2660,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
}
if (pending & SDMMC_INT_DATA_OVER) {
spin_lock_irqsave(&host->irq_lock, irqflags);
spin_lock(&host->irq_lock);
del_timer(&host->dto_timer);
@ -2676,7 +2675,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
set_bit(EVENT_DATA_COMPLETE, &host->pending_events);
tasklet_schedule(&host->tasklet);
spin_unlock_irqrestore(&host->irq_lock, irqflags);
spin_unlock(&host->irq_lock);
}
if (pending & SDMMC_INT_RXDR) {
@ -2692,12 +2691,12 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
}
if (pending & SDMMC_INT_CMD_DONE) {
spin_lock_irqsave(&host->irq_lock, irqflags);
spin_lock(&host->irq_lock);
mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE);
dw_mci_cmd_interrupt(host, pending);
spin_unlock_irqrestore(&host->irq_lock, irqflags);
spin_unlock(&host->irq_lock);
}
if (pending & SDMMC_INT_CD) {

View File

@ -1265,7 +1265,7 @@ static struct platform_driver meson_mmc_driver = {
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(meson_mmc_of_match),
.of_match_table = meson_mmc_of_match,
},
};

View File

@ -418,10 +418,9 @@ static irqreturn_t meson_mx_mmc_irq(int irq, void *data)
{
struct meson_mx_mmc_host *host = (void *) data;
u32 irqs, send;
unsigned long irqflags;
irqreturn_t ret;
spin_lock_irqsave(&host->irq_lock, irqflags);
spin_lock(&host->irq_lock);
irqs = readl(host->base + MESON_MX_SDIO_IRQS);
send = readl(host->base + MESON_MX_SDIO_SEND);
@ -434,7 +433,7 @@ static irqreturn_t meson_mx_mmc_irq(int irq, void *data)
/* finally ACK all pending interrupts */
writel(irqs, host->base + MESON_MX_SDIO_IRQS);
spin_unlock_irqrestore(&host->irq_lock, irqflags);
spin_unlock(&host->irq_lock);
return ret;
}

View File

@ -465,9 +465,8 @@ static irqreturn_t moxart_irq(int irq, void *devid)
{
struct moxart_host *host = (struct moxart_host *)devid;
u32 status;
unsigned long flags;
spin_lock_irqsave(&host->lock, flags);
spin_lock(&host->lock);
status = readl(host->base + REG_STATUS);
if (status & CARD_CHANGE) {
@ -484,7 +483,7 @@ static irqreturn_t moxart_irq(int irq, void *devid)
if (status & (FIFO_ORUN | FIFO_URUN) && host->mrq)
moxart_transfer_pio(host);
spin_unlock_irqrestore(&host->lock, flags);
spin_unlock(&host->lock);
return IRQ_HANDLED;
}

View File

@ -35,6 +35,7 @@
#include "cqhci.h"
#define MAX_BD_NUM 1024
#define MSDC_NR_CLOCKS 3
/*--------------------------------------------------------------------------*/
/* Common Definition */
@ -77,9 +78,12 @@
#define MSDC_PAD_TUNE0 0xf0
#define PAD_DS_TUNE 0x188
#define PAD_CMD_TUNE 0x18c
#define EMMC51_CFG0 0x204
#define EMMC50_CFG0 0x208
#define EMMC50_CFG1 0x20c
#define EMMC50_CFG3 0x220
#define SDC_FIFO_CFG 0x228
#define CQHCI_SETTING 0x7fc
/*--------------------------------------------------------------------------*/
/* Top Pad Register Offset */
@ -260,15 +264,26 @@
#define PAD_CMD_TUNE_RX_DLY3 (0x1f << 1) /* RW */
/* EMMC51_CFG0 mask */
#define CMDQ_RDAT_CNT (0x3ff << 12) /* RW */
#define EMMC50_CFG_PADCMD_LATCHCK (0x1 << 0) /* RW */
#define EMMC50_CFG_CRCSTS_EDGE (0x1 << 3) /* RW */
#define EMMC50_CFG_CFCSTS_SEL (0x1 << 4) /* RW */
#define EMMC50_CFG_CMD_RESP_SEL (0x1 << 9) /* RW */
/* EMMC50_CFG1 mask */
#define EMMC50_CFG1_DS_CFG (0x1 << 28) /* RW */
#define EMMC50_CFG3_OUTS_WR (0x1f << 0) /* RW */
#define SDC_FIFO_CFG_WRVALIDSEL (0x1 << 24) /* RW */
#define SDC_FIFO_CFG_RDVALIDSEL (0x1 << 25) /* RW */
/* CQHCI_SETTING */
#define CQHCI_RD_CMD_WND_SEL (0x1 << 14) /* RW */
#define CQHCI_WR_CMD_WND_SEL (0x1 << 15) /* RW */
/* EMMC_TOP_CONTROL mask */
#define PAD_RXDLY_SEL (0x1 << 0) /* RW */
#define DELAY_EN (0x1 << 1) /* RW */
@ -425,6 +440,8 @@ struct msdc_host {
struct clk *h_clk; /* msdc h_clk */
struct clk *bus_clk; /* bus clock which used to access register */
struct clk *src_clk_cg; /* msdc source clock control gate */
struct clk *sys_clk_cg; /* msdc subsys clock control gate */
struct clk_bulk_data bulk_clks[MSDC_NR_CLOCKS];
u32 mclk; /* mmc subsystem clock frequency */
u32 src_clk_freq; /* source clock frequency */
unsigned char timing;
@ -785,6 +802,7 @@ static void msdc_set_busy_timeout(struct msdc_host *host, u64 ns, u64 clks)
static void msdc_gate_clock(struct msdc_host *host)
{
clk_bulk_disable_unprepare(MSDC_NR_CLOCKS, host->bulk_clks);
clk_disable_unprepare(host->src_clk_cg);
clk_disable_unprepare(host->src_clk);
clk_disable_unprepare(host->bus_clk);
@ -793,10 +811,18 @@ static void msdc_gate_clock(struct msdc_host *host)
static void msdc_ungate_clock(struct msdc_host *host)
{
int ret;
clk_prepare_enable(host->h_clk);
clk_prepare_enable(host->bus_clk);
clk_prepare_enable(host->src_clk);
clk_prepare_enable(host->src_clk_cg);
ret = clk_bulk_prepare_enable(MSDC_NR_CLOCKS, host->bulk_clks);
if (ret) {
dev_err(host->dev, "Cannot enable pclk/axi/ahb clock gates\n");
return;
}
while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
cpu_relax();
}
@ -1537,13 +1563,12 @@ static irqreturn_t msdc_irq(int irq, void *dev_id)
struct mmc_host *mmc = mmc_from_priv(host);
while (true) {
unsigned long flags;
struct mmc_request *mrq;
struct mmc_command *cmd;
struct mmc_data *data;
u32 events, event_mask;
spin_lock_irqsave(&host->lock, flags);
spin_lock(&host->lock);
events = readl(host->base + MSDC_INT);
event_mask = readl(host->base + MSDC_INTEN);
if ((events & event_mask) & MSDC_INT_SDIOIRQ)
@ -1554,7 +1579,7 @@ static irqreturn_t msdc_irq(int irq, void *dev_id)
mrq = host->mrq;
cmd = host->cmd;
data = host->data;
spin_unlock_irqrestore(&host->lock, flags);
spin_unlock(&host->lock);
if ((events & event_mask) & MSDC_INT_SDIOIRQ)
sdio_signal_irq(mmc);
@ -2266,6 +2291,31 @@ static int msdc_get_cd(struct mmc_host *mmc)
return !val;
}
static void msdc_hs400_enhanced_strobe(struct mmc_host *mmc,
struct mmc_ios *ios)
{
struct msdc_host *host = mmc_priv(mmc);
if (ios->enhanced_strobe) {
msdc_prepare_hs400_tuning(mmc, ios);
sdr_set_field(host->base + EMMC50_CFG0, EMMC50_CFG_PADCMD_LATCHCK, 1);
sdr_set_field(host->base + EMMC50_CFG0, EMMC50_CFG_CMD_RESP_SEL, 1);
sdr_set_field(host->base + EMMC50_CFG1, EMMC50_CFG1_DS_CFG, 1);
sdr_clr_bits(host->base + CQHCI_SETTING, CQHCI_RD_CMD_WND_SEL);
sdr_clr_bits(host->base + CQHCI_SETTING, CQHCI_WR_CMD_WND_SEL);
sdr_clr_bits(host->base + EMMC51_CFG0, CMDQ_RDAT_CNT);
} else {
sdr_set_field(host->base + EMMC50_CFG0, EMMC50_CFG_PADCMD_LATCHCK, 0);
sdr_set_field(host->base + EMMC50_CFG0, EMMC50_CFG_CMD_RESP_SEL, 0);
sdr_set_field(host->base + EMMC50_CFG1, EMMC50_CFG1_DS_CFG, 0);
sdr_set_bits(host->base + CQHCI_SETTING, CQHCI_RD_CMD_WND_SEL);
sdr_set_bits(host->base + CQHCI_SETTING, CQHCI_WR_CMD_WND_SEL);
sdr_set_field(host->base + EMMC51_CFG0, CMDQ_RDAT_CNT, 0xb4);
}
}
static void msdc_cqe_enable(struct mmc_host *mmc)
{
struct msdc_host *host = mmc_priv(mmc);
@ -2323,6 +2373,7 @@ static const struct mmc_host_ops mt_msdc_ops = {
.set_ios = msdc_ops_set_ios,
.get_ro = mmc_gpio_get_ro,
.get_cd = msdc_get_cd,
.hs400_enhanced_strobe = msdc_hs400_enhanced_strobe,
.enable_sdio_irq = msdc_enable_sdio_irq,
.ack_sdio_irq = msdc_ack_sdio_irq,
.start_signal_voltage_switch = msdc_ops_switch_volt,
@ -2367,6 +2418,48 @@ static void msdc_of_property_parse(struct platform_device *pdev,
host->cqhci = false;
}
static int msdc_of_clock_parse(struct platform_device *pdev,
struct msdc_host *host)
{
int ret;
host->src_clk = devm_clk_get(&pdev->dev, "source");
if (IS_ERR(host->src_clk))
return PTR_ERR(host->src_clk);
host->h_clk = devm_clk_get(&pdev->dev, "hclk");
if (IS_ERR(host->h_clk))
return PTR_ERR(host->h_clk);
host->bus_clk = devm_clk_get_optional(&pdev->dev, "bus_clk");
if (IS_ERR(host->bus_clk))
host->bus_clk = NULL;
/*source clock control gate is optional clock*/
host->src_clk_cg = devm_clk_get_optional(&pdev->dev, "source_cg");
if (IS_ERR(host->src_clk_cg))
host->src_clk_cg = NULL;
host->sys_clk_cg = devm_clk_get_optional(&pdev->dev, "sys_cg");
if (IS_ERR(host->sys_clk_cg))
host->sys_clk_cg = NULL;
/* If present, always enable for this clock gate */
clk_prepare_enable(host->sys_clk_cg);
host->bulk_clks[0].id = "pclk_cg";
host->bulk_clks[1].id = "axi_cg";
host->bulk_clks[2].id = "ahb_cg";
ret = devm_clk_bulk_get_optional(&pdev->dev, MSDC_NR_CLOCKS,
host->bulk_clks);
if (ret) {
dev_err(&pdev->dev, "Cannot get pclk/axi/ahb clock gates\n");
return ret;
}
return 0;
}
static int msdc_drv_probe(struct platform_device *pdev)
{
struct mmc_host *mmc;
@ -2406,30 +2499,16 @@ static int msdc_drv_probe(struct platform_device *pdev)
if (ret)
goto host_free;
host->src_clk = devm_clk_get(&pdev->dev, "source");
if (IS_ERR(host->src_clk)) {
ret = PTR_ERR(host->src_clk);
ret = msdc_of_clock_parse(pdev, host);
if (ret)
goto host_free;
}
host->h_clk = devm_clk_get(&pdev->dev, "hclk");
if (IS_ERR(host->h_clk)) {
ret = PTR_ERR(host->h_clk);
goto host_free;
}
host->bus_clk = devm_clk_get(&pdev->dev, "bus_clk");
if (IS_ERR(host->bus_clk))
host->bus_clk = NULL;
/*source clock control gate is optional clock*/
host->src_clk_cg = devm_clk_get(&pdev->dev, "source_cg");
if (IS_ERR(host->src_clk_cg))
host->src_clk_cg = NULL;
host->reset = devm_reset_control_get_optional_exclusive(&pdev->dev,
"hrst");
if (IS_ERR(host->reset))
return PTR_ERR(host->reset);
if (IS_ERR(host->reset)) {
ret = PTR_ERR(host->reset);
goto host_free;
}
host->irq = platform_get_irq(pdev, 0);
if (host->irq < 0) {

View File

@ -157,32 +157,16 @@ struct mxcmci_host {
enum mxcmci_type devtype;
};
static const struct platform_device_id mxcmci_devtype[] = {
{
.name = "imx21-mmc",
.driver_data = IMX21_MMC,
}, {
.name = "imx31-mmc",
.driver_data = IMX31_MMC,
}, {
.name = "mpc512x-sdhc",
.driver_data = MPC512X_MMC,
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(platform, mxcmci_devtype);
static const struct of_device_id mxcmci_of_match[] = {
{
.compatible = "fsl,imx21-mmc",
.data = &mxcmci_devtype[IMX21_MMC],
.data = (void *) IMX21_MMC,
}, {
.compatible = "fsl,imx31-mmc",
.data = &mxcmci_devtype[IMX31_MMC],
.data = (void *) IMX31_MMC,
}, {
.compatible = "fsl,mpc5121-sdhc",
.data = &mxcmci_devtype[MPC512X_MMC],
.data = (void *) MPC512X_MMC,
}, {
/* sentinel */
}
@ -1001,13 +985,10 @@ static int mxcmci_probe(struct platform_device *pdev)
int ret = 0, irq;
bool dat3_card_detect = false;
dma_cap_mask_t mask;
const struct of_device_id *of_id;
struct imxmmc_platform_data *pdata = pdev->dev.platform_data;
pr_info("i.MX/MPC512x SDHC driver\n");
of_id = of_match_device(mxcmci_of_match, &pdev->dev);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_irq(pdev, 0);
if (irq < 0)
@ -1044,12 +1025,7 @@ static int mxcmci_probe(struct platform_device *pdev)
mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
mmc->max_seg_size = mmc->max_req_size;
if (of_id) {
const struct platform_device_id *id_entry = of_id->data;
host->devtype = id_entry->driver_data;
} else {
host->devtype = pdev->id_entry->driver_data;
}
host->devtype = (enum mxcmci_type)of_device_get_match_data(&pdev->dev);
/* adjust max_segs after devtype detection */
if (!is_mpc512x_mmc(host))
@ -1241,7 +1217,6 @@ static SIMPLE_DEV_PM_OPS(mxcmci_pm_ops, mxcmci_suspend, mxcmci_resume);
static struct platform_driver mxcmci_driver = {
.probe = mxcmci_probe,
.remove = mxcmci_remove,
.id_table = mxcmci_devtype,
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View File

@ -545,19 +545,6 @@ static const struct mmc_host_ops mxs_mmc_ops = {
.enable_sdio_irq = mxs_mmc_enable_sdio_irq,
};
static const struct platform_device_id mxs_ssp_ids[] = {
{
.name = "imx23-mmc",
.driver_data = IMX23_SSP,
}, {
.name = "imx28-mmc",
.driver_data = IMX28_SSP,
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(platform, mxs_ssp_ids);
static const struct of_device_id mxs_mmc_dt_ids[] = {
{ .compatible = "fsl,imx23-mmc", .data = (void *) IMX23_SSP, },
{ .compatible = "fsl,imx28-mmc", .data = (void *) IMX28_SSP, },
@ -567,8 +554,6 @@ MODULE_DEVICE_TABLE(of, mxs_mmc_dt_ids);
static int mxs_mmc_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id =
of_match_device(mxs_mmc_dt_ids, &pdev->dev);
struct device_node *np = pdev->dev.of_node;
struct mxs_mmc_host *host;
struct mmc_host *mmc;
@ -593,7 +578,7 @@ static int mxs_mmc_probe(struct platform_device *pdev)
goto out_mmc_free;
}
ssp->devid = (enum mxs_ssp_id) of_id->data;
ssp->devid = (enum mxs_ssp_id)of_device_get_match_data(&pdev->dev);
host->mmc = mmc;
host->sdio_irq_en = 0;
@ -723,7 +708,6 @@ static SIMPLE_DEV_PM_OPS(mxs_mmc_pm_ops, mxs_mmc_suspend, mxs_mmc_resume);
static struct platform_driver mxs_mmc_driver = {
.probe = mxs_mmc_probe,
.remove = mxs_mmc_remove,
.id_table = mxs_ssp_ids,
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View File

@ -134,10 +134,9 @@ static void owl_mmc_update_reg(void __iomem *reg, unsigned int val, bool state)
static irqreturn_t owl_irq_handler(int irq, void *devid)
{
struct owl_mmc_host *owl_host = devid;
unsigned long flags;
u32 state;
spin_lock_irqsave(&owl_host->lock, flags);
spin_lock(&owl_host->lock);
state = readl(owl_host->base + OWL_REG_SD_STATE);
if (state & OWL_SD_STATE_TEI) {
@ -147,7 +146,7 @@ static irqreturn_t owl_irq_handler(int irq, void *devid)
complete(&owl_host->sdc_complete);
}
spin_unlock_irqrestore(&owl_host->lock, flags);
spin_unlock(&owl_host->lock);
return IRQ_HANDLED;
}
@ -522,11 +521,11 @@ static void owl_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
/* Enable DDR mode if requested */
if (ios->timing == MMC_TIMING_UHS_DDR50) {
owl_host->ddr_50 = 1;
owl_host->ddr_50 = true;
owl_mmc_update_reg(owl_host->base + OWL_REG_SD_EN,
OWL_SD_EN_DDREN, true);
} else {
owl_host->ddr_50 = 0;
owl_host->ddr_50 = false;
}
}

View File

@ -731,6 +731,7 @@ static int pxamci_probe(struct platform_device *pdev)
host->power = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW);
if (IS_ERR(host->power)) {
ret = PTR_ERR(host->power);
dev_err(dev, "Failed requesting gpio_power\n");
goto out;
}

View File

@ -18,28 +18,39 @@
*
*/
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/mfd/tmio.h>
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/slot-gpio.h>
#include <linux/mfd/tmio.h>
#include <linux/sh_dma.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/pinctrl-state.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/regulator/consumer.h>
#include <linux/sh_dma.h>
#include <linux/slab.h>
#include <linux/sys_soc.h>
#include "renesas_sdhi.h"
#include "tmio_mmc.h"
#define HOST_MODE 0xe4
#define CTL_HOST_MODE 0xe4
#define HOST_MODE_GEN2_SDR50_WMODE BIT(0)
#define HOST_MODE_GEN2_SDR104_WMODE BIT(0)
#define HOST_MODE_GEN3_WMODE BIT(0)
#define HOST_MODE_GEN3_BUSWIDTH BIT(8)
#define HOST_MODE_GEN3_16BIT HOST_MODE_GEN3_WMODE
#define HOST_MODE_GEN3_32BIT (HOST_MODE_GEN3_WMODE | HOST_MODE_GEN3_BUSWIDTH)
#define HOST_MODE_GEN3_64BIT 0
#define CTL_SDIF_MODE 0xe6
#define SDIF_MODE_HS400 BIT(0)
#define SDHI_VER_GEN2_SDR50 0x490c
#define SDHI_VER_RZ_A1 0x820b
@ -60,26 +71,26 @@ static void renesas_sdhi_sdbuf_width(struct tmio_mmc_host *host, int width)
*/
switch (sd_ctrl_read16(host, CTL_VERSION)) {
case SDHI_VER_GEN2_SDR50:
val = (width == 32) ? 0x0001 : 0x0000;
val = (width == 32) ? HOST_MODE_GEN2_SDR50_WMODE : 0;
break;
case SDHI_VER_GEN2_SDR104:
val = (width == 32) ? 0x0000 : 0x0001;
val = (width == 32) ? 0 : HOST_MODE_GEN2_SDR104_WMODE;
break;
case SDHI_VER_GEN3_SD:
case SDHI_VER_GEN3_SDMMC:
if (width == 64)
val = 0x0000;
val = HOST_MODE_GEN3_64BIT;
else if (width == 32)
val = 0x0101;
val = HOST_MODE_GEN3_32BIT;
else
val = 0x0001;
val = HOST_MODE_GEN3_16BIT;
break;
default:
/* nothing to do */
return;
}
sd_ctrl_write16(host, HOST_MODE, val);
sd_ctrl_write16(host, CTL_HOST_MODE, val);
}
static int renesas_sdhi_clk_enable(struct tmio_mmc_host *host)
@ -373,7 +384,7 @@ static void renesas_sdhi_hs400_complete(struct mmc_host *mmc)
sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
/* Set HS400 mode */
sd_ctrl_write16(host, CTL_SDIF_MODE, 0x0001 |
sd_ctrl_write16(host, CTL_SDIF_MODE, SDIF_MODE_HS400 |
sd_ctrl_read16(host, CTL_SDIF_MODE));
sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DT2FF,
@ -424,9 +435,11 @@ static void renesas_sdhi_hs400_complete(struct mmc_host *mmc)
priv->needs_adjust_hs400 = true;
}
static void renesas_sdhi_reset_scc(struct tmio_mmc_host *host,
struct renesas_sdhi *priv)
static void renesas_sdhi_disable_scc(struct mmc_host *mmc)
{
struct tmio_mmc_host *host = mmc_priv(mmc);
struct renesas_sdhi *priv = host_to_priv(host);
sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN &
sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
@ -434,14 +447,6 @@ static void renesas_sdhi_reset_scc(struct tmio_mmc_host *host,
~SH_MOBILE_SDHI_SCC_CKSEL_DTSEL &
sd_scc_read32(host, priv,
SH_MOBILE_SDHI_SCC_CKSEL));
}
static void renesas_sdhi_disable_scc(struct mmc_host *mmc)
{
struct tmio_mmc_host *host = mmc_priv(mmc);
struct renesas_sdhi *priv = host_to_priv(host);
renesas_sdhi_reset_scc(host, priv);
sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL,
~SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN &
@ -527,7 +532,7 @@ static void renesas_sdhi_reset_hs400_mode(struct tmio_mmc_host *host,
sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
/* Reset HS400 mode */
sd_ctrl_write16(host, CTL_SDIF_MODE, ~0x0001 &
sd_ctrl_write16(host, CTL_SDIF_MODE, ~SDIF_MODE_HS400 &
sd_ctrl_read16(host, CTL_SDIF_MODE));
sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DT2FF, priv->scc_tappos);
@ -552,24 +557,38 @@ static int renesas_sdhi_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_io
return 0;
}
/* only populated for TMIO_MMC_MIN_RCAR2 */
static void renesas_sdhi_reset(struct tmio_mmc_host *host)
{
struct renesas_sdhi *priv = host_to_priv(host);
u16 val;
renesas_sdhi_reset_scc(host, priv);
renesas_sdhi_reset_hs400_mode(host, priv);
priv->needs_adjust_hs400 = false;
if (priv->scc_ctl) {
renesas_sdhi_disable_scc(host->mmc);
renesas_sdhi_reset_hs400_mode(host, priv);
priv->needs_adjust_hs400 = false;
sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN |
sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL,
~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN &
sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL));
}
sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL,
~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN &
sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL));
sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, TMIO_MASK_INIT_RCAR2);
if (sd_ctrl_read16(host, CTL_VERSION) >= SDHI_VER_GEN3_SD) {
val = sd_ctrl_read16(host, CTL_SD_MEM_CARD_OPT);
val |= CARD_OPT_EXTOP;
sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, val);
}
}
static unsigned int renesas_sdhi_gen3_get_cycles(struct tmio_mmc_host *host)
{
u16 num, val = sd_ctrl_read16(host, CTL_SD_MEM_CARD_OPT);
num = (val & CARD_OPT_TOP_MASK) >> CARD_OPT_TOP_SHIFT;
return 1 << ((val & CARD_OPT_EXTOP ? 14 : 13) + num);
if (host->pdata->flags & TMIO_MMC_MIN_RCAR2)
sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK,
TMIO_MASK_INIT_RCAR2);
}
#define SH_MOBILE_SDHI_MIN_TAP_ROW 3
@ -803,7 +822,7 @@ static int renesas_sdhi_write16_hook(struct tmio_mmc_host *host, int addr)
case CTL_SD_MEM_CARD_OPT:
case CTL_TRANSACTION_CTL:
case CTL_DMA_ENABLE:
case HOST_MODE:
case CTL_HOST_MODE:
if (host->pdata->flags & TMIO_MMC_HAVE_CBSY)
bit = TMIO_STAT_CMD_BUSY;
fallthrough;
@ -1005,11 +1024,7 @@ int renesas_sdhi_probe(struct platform_device *pdev,
host->ops.start_signal_voltage_switch =
renesas_sdhi_start_signal_voltage_switch;
host->sdcard_irq_setbit_mask = TMIO_STAT_ALWAYS_SET_27;
if (of_data && of_data->scc_offset) {
priv->scc_ctl = host->ctl + of_data->scc_offset;
host->reset = renesas_sdhi_reset;
}
host->reset = renesas_sdhi_reset;
}
/* Orginally registers were 16 bit apart, could be 32 or 64 nowadays */
@ -1042,6 +1057,9 @@ int renesas_sdhi_probe(struct platform_device *pdev,
/* All SDHI have SDIO status bits which must be 1 */
mmc_data->flags |= TMIO_MMC_SDIO_STATUS_SETBITS;
/* All SDHI support HW busy detection */
mmc_data->flags |= TMIO_MMC_USE_BUSY_TIMEOUT;
dev_pm_domain_start(&pdev->dev);
ret = renesas_sdhi_clk_enable(host);
@ -1065,9 +1083,9 @@ int renesas_sdhi_probe(struct platform_device *pdev,
quirks->hs400_calib_table + 1);
}
ret = tmio_mmc_host_probe(host);
if (ret < 0)
goto edisclk;
/* these have an EXTOP bit */
if (ver >= SDHI_VER_GEN3_SD)
host->get_timeout_cycles = renesas_sdhi_gen3_get_cycles;
/* Enable tuning iff we have an SCC and a supported mode */
if (of_data && of_data->scc_offset &&
@ -1093,6 +1111,7 @@ int renesas_sdhi_probe(struct platform_device *pdev,
if (!hit)
dev_warn(&host->pdev->dev, "Unknown clock rate for tuning\n");
priv->scc_ctl = host->ctl + of_data->scc_offset;
host->check_retune = renesas_sdhi_check_scc_error;
host->ops.execute_tuning = renesas_sdhi_execute_tuning;
host->ops.prepare_hs400_tuning = renesas_sdhi_prepare_hs400_tuning;
@ -1100,6 +1119,10 @@ int renesas_sdhi_probe(struct platform_device *pdev,
host->ops.hs400_complete = renesas_sdhi_hs400_complete;
}
ret = tmio_mmc_host_probe(host);
if (ret < 0)
goto edisclk;
num_irqs = platform_irq_count(pdev);
if (num_irqs < 0) {
ret = num_irqs;

View File

@ -48,6 +48,8 @@ struct realtek_pci_sdmmc {
bool using_cookie;
};
static int sdmmc_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios);
static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host)
{
return &(host->pdev->dev);
@ -896,7 +898,10 @@ static int sd_set_bus_width(struct realtek_pci_sdmmc *host,
static int sd_power_on(struct realtek_pci_sdmmc *host)
{
struct rtsx_pcr *pcr = host->pcr;
struct mmc_host *mmc = host->mmc;
int err;
u32 val;
u8 test_mode;
if (host->power_state == SDMMC_POWER_ON)
return 0;
@ -923,6 +928,30 @@ static int sd_power_on(struct realtek_pci_sdmmc *host)
if (err < 0)
return err;
if (PCI_PID(pcr) == PID_5261) {
/*
* If test mode is set switch to SD Express mandatorily,
* this is only for factory testing.
*/
rtsx_pci_read_register(pcr, RTS5261_FW_CFG_INFO0, &test_mode);
if (test_mode & RTS5261_FW_EXPRESS_TEST_MASK) {
sdmmc_init_sd_express(mmc, NULL);
return 0;
}
if (pcr->extra_caps & EXTRA_CAPS_SD_EXPRESS)
mmc->caps2 |= MMC_CAP2_SD_EXP | MMC_CAP2_SD_EXP_1_2V;
/*
* HW read wp status when resuming from S3/S4,
* and then picks SD legacy interface if it's set
* in read-only mode.
*/
val = rtsx_pci_readl(pcr, RTSX_BIPR);
if (val & SD_WRITE_PROTECT) {
pcr->extra_caps &= ~EXTRA_CAPS_SD_EXPRESS;
mmc->caps2 &= ~(MMC_CAP2_SD_EXP | MMC_CAP2_SD_EXP_1_2V);
}
}
host->power_state = SDMMC_POWER_ON;
return 0;
}
@ -1309,6 +1338,45 @@ static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
return err;
}
static int sdmmc_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios)
{
u32 relink_time;
struct realtek_pci_sdmmc *host = mmc_priv(mmc);
struct rtsx_pcr *pcr = host->pcr;
/* Set relink_time for changing to PCIe card */
relink_time = 0x8FFF;
rtsx_pci_write_register(pcr, 0xFF01, 0xFF, relink_time);
rtsx_pci_write_register(pcr, 0xFF02, 0xFF, relink_time >> 8);
rtsx_pci_write_register(pcr, 0xFF03, 0x01, relink_time >> 16);
rtsx_pci_write_register(pcr, PETXCFG, 0x80, 0x80);
rtsx_pci_write_register(pcr, LDO_VCC_CFG0,
RTS5261_LDO1_OCP_THD_MASK,
pcr->option.sd_800mA_ocp_thd);
if (pcr->ops->disable_auto_blink)
pcr->ops->disable_auto_blink(pcr);
/* For PCIe/NVMe mode can't enter delink issue */
pcr->hw_param.interrupt_en &= ~(SD_INT_EN);
rtsx_pci_writel(pcr, RTSX_BIER, pcr->hw_param.interrupt_en);
rtsx_pci_write_register(pcr, RTS5260_AUTOLOAD_CFG4,
RTS5261_AUX_CLK_16M_EN, RTS5261_AUX_CLK_16M_EN);
rtsx_pci_write_register(pcr, RTS5261_FW_CFG0,
RTS5261_FW_ENTER_EXPRESS, RTS5261_FW_ENTER_EXPRESS);
rtsx_pci_write_register(pcr, RTS5261_FW_CFG1,
RTS5261_MCU_CLOCK_GATING, RTS5261_MCU_CLOCK_GATING);
rtsx_pci_write_register(pcr, RTS5261_FW_CFG1,
RTS5261_MCU_BUS_SEL_MASK | RTS5261_MCU_CLOCK_SEL_MASK
| RTS5261_DRIVER_ENABLE_FW,
RTS5261_MCU_CLOCK_SEL_16M | RTS5261_DRIVER_ENABLE_FW);
host->eject = true;
return 0;
}
static const struct mmc_host_ops realtek_pci_sdmmc_ops = {
.pre_req = sdmmc_pre_req,
.post_req = sdmmc_post_req,
@ -1318,6 +1386,7 @@ static const struct mmc_host_ops realtek_pci_sdmmc_ops = {
.get_cd = sdmmc_get_cd,
.start_signal_voltage_switch = sdmmc_switch_voltage,
.execute_tuning = sdmmc_execute_tuning,
.init_sd_express = sdmmc_init_sd_express,
};
static void init_extra_caps(struct realtek_pci_sdmmc *host)
@ -1339,6 +1408,8 @@ static void init_extra_caps(struct realtek_pci_sdmmc *host)
mmc->caps |= MMC_CAP_8_BIT_DATA;
if (pcr->extra_caps & EXTRA_CAPS_NO_MMC)
mmc->caps2 |= MMC_CAP2_NO_MMC;
if (pcr->extra_caps & EXTRA_CAPS_SD_EXPRESS)
mmc->caps2 |= MMC_CAP2_SD_EXP | MMC_CAP2_SD_EXP_1_2V;
}
static void realtek_init_host(struct realtek_pci_sdmmc *host)

View File

@ -17,7 +17,7 @@
#include <linux/cpufreq.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/io.h>

View File

@ -5,6 +5,7 @@
* Copyright (c) 2012, Intel Corporation.
*/
#include <linux/bitfield.h>
#include <linux/init.h>
#include <linux/export.h>
#include <linux/module.h>
@ -545,10 +546,41 @@ struct amd_sdhci_host {
static int amd_select_drive_strength(struct mmc_card *card,
unsigned int max_dtr, int host_drv,
int card_drv, int *drv_type)
int card_drv, int *host_driver_strength)
{
*drv_type = MMC_SET_DRIVER_TYPE_A;
return MMC_SET_DRIVER_TYPE_A;
struct sdhci_host *host = mmc_priv(card->host);
u16 preset, preset_driver_strength;
/*
* This method is only called by mmc_select_hs200 so we only need to
* read from the HS200 (SDR104) preset register.
*
* Firmware that has "invalid/default" presets return a driver strength
* of A. This matches the previously hard coded value.
*/
preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104);
preset_driver_strength = FIELD_GET(SDHCI_PRESET_DRV_MASK, preset);
/*
* We want the controller driver strength to match the card's driver
* strength so they have similar rise/fall times.
*
* The controller driver strength set by this method is sticky for all
* timings after this method is called. This unfortunately means that
* while HS400 tuning is in progress we end up with mismatched driver
* strengths between the controller and the card. HS400 tuning requires
* switching from HS400->DDR52->HS->HS200->HS400. So the driver mismatch
* happens while in DDR52 and HS modes. This has not been observed to
* cause problems. Enabling presets would fix this issue.
*/
*host_driver_strength = preset_driver_strength;
/*
* The resulting card driver strength is only set when switching the
* card's timing to HS200 or HS400. The card will use the default driver
* strength (B) for any other mode.
*/
return preset_driver_strength;
}
static void sdhci_acpi_amd_hs400_dll(struct sdhci_host *host, bool enable)

View File

@ -296,22 +296,6 @@ struct pltfm_imx_data {
struct pm_qos_request pm_qos_req;
};
static const struct platform_device_id imx_esdhc_devtype[] = {
{
.name = "sdhci-esdhc-imx25",
.driver_data = (kernel_ulong_t) &esdhc_imx25_data,
}, {
.name = "sdhci-esdhc-imx35",
.driver_data = (kernel_ulong_t) &esdhc_imx35_data,
}, {
.name = "sdhci-esdhc-imx51",
.driver_data = (kernel_ulong_t) &esdhc_imx51_data,
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(platform, imx_esdhc_devtype);
static const struct of_device_id imx_esdhc_dt_ids[] = {
{ .compatible = "fsl,imx25-esdhc", .data = &esdhc_imx25_data, },
{ .compatible = "fsl,imx35-esdhc", .data = &esdhc_imx35_data, },
@ -1531,72 +1515,6 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
}
#endif
static int sdhci_esdhc_imx_probe_nondt(struct platform_device *pdev,
struct sdhci_host *host,
struct pltfm_imx_data *imx_data)
{
struct esdhc_platform_data *boarddata = &imx_data->boarddata;
int err;
if (!host->mmc->parent->platform_data) {
dev_err(mmc_dev(host->mmc), "no board data!\n");
return -EINVAL;
}
imx_data->boarddata = *((struct esdhc_platform_data *)
host->mmc->parent->platform_data);
/* write_protect */
if (boarddata->wp_type == ESDHC_WP_GPIO) {
host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
err = mmc_gpiod_request_ro(host->mmc, "wp", 0, 0);
if (err) {
dev_err(mmc_dev(host->mmc),
"failed to request write-protect gpio!\n");
return err;
}
}
/* card_detect */
switch (boarddata->cd_type) {
case ESDHC_CD_GPIO:
err = mmc_gpiod_request_cd(host->mmc, "cd", 0, false, 0);
if (err) {
dev_err(mmc_dev(host->mmc),
"failed to request card-detect gpio!\n");
return err;
}
fallthrough;
case ESDHC_CD_CONTROLLER:
/* we have a working card_detect back */
host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
break;
case ESDHC_CD_PERMANENT:
host->mmc->caps |= MMC_CAP_NONREMOVABLE;
break;
case ESDHC_CD_NONE:
break;
}
switch (boarddata->max_bus_width) {
case 8:
host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA;
break;
case 4:
host->mmc->caps |= MMC_CAP_4_BIT_DATA;
break;
case 1:
default:
host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
break;
}
return 0;
}
static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id =
@ -1616,8 +1534,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
imx_data = sdhci_pltfm_priv(pltfm_host);
imx_data->socdata = of_id ? of_id->data : (struct esdhc_soc_data *)
pdev->id_entry->driver_data;
imx_data->socdata = of_id->data;
if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS)
cpu_latency_qos_add_request(&imx_data->pm_qos_req, 0);
@ -1713,10 +1630,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
goto disable_ahb_clk;
}
if (of_id)
err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data);
else
err = sdhci_esdhc_imx_probe_nondt(pdev, host, imx_data);
err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data);
if (err)
goto disable_ahb_clk;
@ -1929,7 +1843,6 @@ static struct platform_driver sdhci_esdhc_imx_driver = {
.of_match_table = imx_esdhc_dt_ids,
.pm = &sdhci_esdhc_pmops,
},
.id_table = imx_esdhc_devtype,
.probe = sdhci_esdhc_imx_probe,
.remove = sdhci_esdhc_imx_remove,
};

View File

@ -248,7 +248,6 @@ struct sdhci_msm_variant_ops {
struct sdhci_msm_variant_info {
bool mci_removed;
bool restore_dll_config;
bool uses_tassadar_dll;
const struct sdhci_msm_variant_ops *var_ops;
const struct sdhci_msm_offset *offset;
};
@ -2154,18 +2153,10 @@ static const struct sdhci_msm_variant_info sdm845_sdhci_var = {
.offset = &sdhci_msm_v5_offset,
};
static const struct sdhci_msm_variant_info sm8250_sdhci_var = {
.mci_removed = true,
.uses_tassadar_dll = true,
.var_ops = &v5_var_ops,
.offset = &sdhci_msm_v5_offset,
};
static const struct of_device_id sdhci_msm_dt_match[] = {
{.compatible = "qcom,sdhci-msm-v4", .data = &sdhci_msm_mci_var},
{.compatible = "qcom,sdhci-msm-v5", .data = &sdhci_msm_v5_var},
{.compatible = "qcom,sdm845-sdhci", .data = &sdm845_sdhci_var},
{.compatible = "qcom,sm8250-sdhci", .data = &sm8250_sdhci_var},
{.compatible = "qcom,sc7180-sdhci", .data = &sdm845_sdhci_var},
{},
};
@ -2249,7 +2240,6 @@ static int sdhci_msm_probe(struct platform_device *pdev)
msm_host->restore_dll_config = var_info->restore_dll_config;
msm_host->var_ops = var_info->var_ops;
msm_host->offset = var_info->offset;
msm_host->uses_tassadar_dll = var_info->uses_tassadar_dll;
msm_offset = msm_host->offset;
@ -2396,6 +2386,9 @@ static int sdhci_msm_probe(struct platform_device *pdev)
if (core_major == 1 && core_minor >= 0x49)
msm_host->updated_ddr_cfg = true;
if (core_major == 1 && core_minor >= 0x71)
msm_host->uses_tassadar_dll = true;
ret = sdhci_msm_register_vreg(msm_host);
if (ret)
goto clk_disable;

View File

@ -624,6 +624,7 @@ static int sdhci_zynqmp_sdcardclk_set_phase(struct clk_hw *hw, int degrees)
case MMC_TIMING_MMC_HS200:
/* For 200MHz clock, 8 Taps are available */
tap_max = 8;
break;
default:
break;
}
@ -692,6 +693,7 @@ static int sdhci_zynqmp_sampleclk_set_phase(struct clk_hw *hw, int degrees)
case MMC_TIMING_MMC_HS200:
/* For 200MHz clock, 30 Taps are available */
tap_max = 30;
break;
default:
break;
}
@ -751,6 +753,7 @@ static int sdhci_versal_sdcardclk_set_phase(struct clk_hw *hw, int degrees)
case MMC_TIMING_MMC_HS200:
/* For 200MHz clock, 8 Taps are available */
tap_max = 8;
break;
default:
break;
}
@ -817,6 +820,7 @@ static int sdhci_versal_sampleclk_set_phase(struct clk_hw *hw, int degrees)
case MMC_TIMING_MMC_HS200:
/* For 200MHz clock, 30 Taps are available */
tap_max = 30;
break;
default:
break;
}

View File

@ -87,6 +87,9 @@
#define PCIE_GLI_9763E_SCR 0x8E0
#define GLI_9763E_SCR_AXI_REQ BIT(9)
#define PCIE_GLI_9763E_MMC_CTRL 0x960
#define GLI_9763E_HS400_SLOW BIT(3)
#define SDHCI_GLI_9763E_CQE_BASE_ADDR 0x200
#define GLI_9763E_CQE_TRNS_MODE (SDHCI_TRNS_MULTI | \
SDHCI_TRNS_BLK_CNT_EN | \
@ -97,6 +100,10 @@
#define GLI_9755_WT_EN_ON 0x1
#define GLI_9755_WT_EN_OFF 0x0
#define PCI_GLI_9755_PECONF 0x44
#define PCI_GLI_9755_LFCLK GENMASK(14, 12)
#define PCI_GLI_9755_DMACLK BIT(29)
#define PCI_GLI_9755_PLL 0x64
#define PCI_GLI_9755_PLL_LDIV GENMASK(9, 0)
#define PCI_GLI_9755_PLL_PDIV GENMASK(14, 12)
@ -519,6 +526,21 @@ static void sdhci_gl9755_set_clock(struct sdhci_host *host, unsigned int clock)
sdhci_enable_clk(host, clk);
}
static void gl9755_hw_setting(struct sdhci_pci_slot *slot)
{
struct pci_dev *pdev = slot->chip->pdev;
u32 value;
gl9755_wt_on(pdev);
pci_read_config_dword(pdev, PCI_GLI_9755_PECONF, &value);
value &= ~PCI_GLI_9755_LFCLK;
value &= ~PCI_GLI_9755_DMACLK;
pci_write_config_dword(pdev, PCI_GLI_9755_PECONF, value);
gl9755_wt_off(pdev);
}
static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot)
{
struct sdhci_host *host = slot->host;
@ -534,6 +556,7 @@ static int gli_probe_slot_gl9755(struct sdhci_pci_slot *slot)
{
struct sdhci_host *host = slot->host;
gl9755_hw_setting(slot);
gli_pcie_enable_msi(slot);
slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
sdhci_enable_v4_mode(host);
@ -764,6 +787,10 @@ static void gli_set_gl9763e(struct sdhci_pci_slot *slot)
value |= GLI_9763E_SCR_AXI_REQ;
pci_write_config_dword(pdev, PCIE_GLI_9763E_SCR, value);
pci_read_config_dword(pdev, PCIE_GLI_9763E_MMC_CTRL, &value);
value &= ~GLI_9763E_HS400_SLOW;
pci_write_config_dword(pdev, PCIE_GLI_9763E_MMC_CTRL, value);
pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value);
value &= ~GLI_9763E_VHS_REV;
value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R);

View File

@ -121,10 +121,9 @@ static void pic32_sdhci_shared_bus(struct platform_device *pdev)
writel(bus, host->ioaddr + SDH_SHARED_BUS_CTRL);
}
static int pic32_sdhci_probe_platform(struct platform_device *pdev,
static void pic32_sdhci_probe_platform(struct platform_device *pdev,
struct pic32_sdhci_priv *pdata)
{
int ret = 0;
u32 caps_slot_type;
struct sdhci_host *host = platform_get_drvdata(pdev);
@ -133,8 +132,6 @@ static int pic32_sdhci_probe_platform(struct platform_device *pdev,
caps_slot_type = (host->caps & SDH_CAPS_SDH_SLOT_TYPE_MASK) >> 30;
if (caps_slot_type == SDH_SLOT_TYPE_SHARED_BUS)
pic32_sdhci_shared_bus(pdev);
return ret;
}
static int pic32_sdhci_probe(struct platform_device *pdev)
@ -193,11 +190,7 @@ static int pic32_sdhci_probe(struct platform_device *pdev)
if (ret)
goto err_base_clk;
ret = pic32_sdhci_probe_platform(pdev, sdhci_pdata);
if (ret) {
dev_err(&pdev->dev, "failed to probe platform!\n");
goto err_base_clk;
}
pic32_sdhci_probe_platform(pdev, sdhci_pdata);
ret = sdhci_add_host(host);
if (ret)

View File

@ -788,7 +788,7 @@ static struct platform_driver sdhci_sprd_driver = {
.driver = {
.name = "sdhci_sprd_r11",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(sdhci_sprd_of_match),
.of_match_table = sdhci_sprd_of_match,
.pm = &sdhci_sprd_pm_ops,
},
};

View File

@ -523,7 +523,7 @@ static struct platform_driver sdhci_st_driver = {
.name = "sdhci-st",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.pm = &sdhci_st_pmops,
.of_match_table = of_match_ptr(st_sdhci_match),
.of_match_table = st_sdhci_match,
},
};

View File

@ -1272,7 +1272,7 @@ static void tegra_sdhci_set_timeout(struct sdhci_host *host,
* busy wait mode.
*/
val = sdhci_readl(host, SDHCI_TEGRA_VENDOR_MISC_CTRL);
if (cmd && cmd->busy_timeout >= 11 * HZ)
if (cmd && cmd->busy_timeout >= 11 * MSEC_PER_SEC)
val |= SDHCI_MISC_CTRL_ERASE_TIMEOUT_LIMIT;
else
val &= ~SDHCI_MISC_CTRL_ERASE_TIMEOUT_LIMIT;

View File

@ -651,11 +651,13 @@ static int get_dt_pad_ctrl_data(struct sdhci_host *host,
struct device_node *np,
struct xenon_emmc_phy_params *params)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
int ret = 0;
const char *name;
struct resource iomem;
if (of_device_is_compatible(np, "marvell,armada-3700-sdhci"))
if (priv->hw_version == XENON_A3700)
params->pad_ctrl.set_soc_pad = armada_3700_soc_pad_voltage_set;
else
return 0;
@ -689,35 +691,37 @@ static int get_dt_pad_ctrl_data(struct sdhci_host *host,
return ret;
}
static int xenon_emmc_phy_parse_param_dt(struct sdhci_host *host,
struct device_node *np,
struct xenon_emmc_phy_params *params)
static int xenon_emmc_phy_parse_params(struct sdhci_host *host,
struct device *dev,
struct xenon_emmc_phy_params *params)
{
u32 value;
params->slow_mode = false;
if (of_property_read_bool(np, "marvell,xenon-phy-slow-mode"))
if (device_property_read_bool(dev, "marvell,xenon-phy-slow-mode"))
params->slow_mode = true;
params->znr = XENON_ZNR_DEF_VALUE;
if (!of_property_read_u32(np, "marvell,xenon-phy-znr", &value))
if (!device_property_read_u32(dev, "marvell,xenon-phy-znr", &value))
params->znr = value & XENON_ZNR_MASK;
params->zpr = XENON_ZPR_DEF_VALUE;
if (!of_property_read_u32(np, "marvell,xenon-phy-zpr", &value))
if (!device_property_read_u32(dev, "marvell,xenon-phy-zpr", &value))
params->zpr = value & XENON_ZPR_MASK;
params->nr_tun_times = XENON_TUN_CONSECUTIVE_TIMES;
if (!of_property_read_u32(np, "marvell,xenon-phy-nr-success-tun",
&value))
if (!device_property_read_u32(dev, "marvell,xenon-phy-nr-success-tun",
&value))
params->nr_tun_times = value & XENON_TUN_CONSECUTIVE_TIMES_MASK;
params->tun_step_divider = XENON_TUNING_STEP_DIVIDER;
if (!of_property_read_u32(np, "marvell,xenon-phy-tun-step-divider",
&value))
if (!device_property_read_u32(dev, "marvell,xenon-phy-tun-step-divider",
&value))
params->tun_step_divider = value & 0xFF;
return get_dt_pad_ctrl_data(host, np, params);
if (dev->of_node)
return get_dt_pad_ctrl_data(host, dev->of_node, params);
return 0;
}
/* Set SoC PHY Voltage PAD */
@ -811,7 +815,7 @@ int xenon_phy_adj(struct sdhci_host *host, struct mmc_ios *ios)
return ret;
}
static int xenon_add_phy(struct device_node *np, struct sdhci_host *host,
static int xenon_add_phy(struct device *dev, struct sdhci_host *host,
const char *phy_name)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@ -830,15 +834,15 @@ static int xenon_add_phy(struct device_node *np, struct sdhci_host *host,
if (ret)
return ret;
return xenon_emmc_phy_parse_param_dt(host, np, priv->phy_params);
return xenon_emmc_phy_parse_params(host, dev, priv->phy_params);
}
int xenon_phy_parse_dt(struct device_node *np, struct sdhci_host *host)
int xenon_phy_parse_params(struct device *dev, struct sdhci_host *host)
{
const char *phy_type = NULL;
if (!of_property_read_string(np, "marvell,xenon-phy-type", &phy_type))
return xenon_add_phy(np, host, phy_type);
if (!device_property_read_string(dev, "marvell,xenon-phy-type", &phy_type))
return xenon_add_phy(dev, host, phy_type);
return xenon_add_phy(np, host, "emmc 5.1 phy");
return xenon_add_phy(dev, host, "emmc 5.1 phy");
}

View File

@ -11,6 +11,7 @@
* Special thanks to Video BG4 project team.
*/
#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/ktime.h>
#include <linux/module.h>
@ -247,6 +248,16 @@ static void xenon_voltage_switch(struct sdhci_host *host)
sdhci_readw(host, SDHCI_HOST_CONTROL2);
}
static unsigned int xenon_get_max_clock(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
if (pltfm_host->clk)
return sdhci_pltfm_clk_get_max_clock(host);
else
return pltfm_host->clock;
}
static const struct sdhci_ops sdhci_xenon_ops = {
.voltage_switch = xenon_voltage_switch,
.set_clock = sdhci_set_clock,
@ -254,7 +265,7 @@ static const struct sdhci_ops sdhci_xenon_ops = {
.set_bus_width = sdhci_set_bus_width,
.reset = xenon_reset,
.set_uhs_signaling = xenon_set_uhs_signaling,
.get_max_clock = sdhci_pltfm_clk_get_max_clock,
.get_max_clock = xenon_get_max_clock,
};
static const struct sdhci_pltfm_data sdhci_xenon_pdata = {
@ -407,9 +418,9 @@ static void xenon_replace_mmc_host_ops(struct sdhci_host *host)
* Refer to XENON_SYS_CFG_INFO register
* tun-count: the interval between re-tuning
*/
static int xenon_probe_dt(struct platform_device *pdev)
static int xenon_probe_params(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
struct sdhci_host *host = platform_get_drvdata(pdev);
struct mmc_host *mmc = host->mmc;
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@ -418,11 +429,11 @@ static int xenon_probe_dt(struct platform_device *pdev)
u32 tuning_count;
/* Disable HS200 on Armada AP806 */
if (of_device_is_compatible(np, "marvell,armada-ap806-sdhci"))
if (priv->hw_version == XENON_AP806)
host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200;
sdhc_id = 0x0;
if (!of_property_read_u32(np, "marvell,xenon-sdhc-id", &sdhc_id)) {
if (!device_property_read_u32(dev, "marvell,xenon-sdhc-id", &sdhc_id)) {
nr_sdhc = sdhci_readl(host, XENON_SYS_CFG_INFO);
nr_sdhc &= XENON_NR_SUPPORTED_SLOT_MASK;
if (unlikely(sdhc_id > nr_sdhc)) {
@ -434,8 +445,8 @@ static int xenon_probe_dt(struct platform_device *pdev)
priv->sdhc_id = sdhc_id;
tuning_count = XENON_DEF_TUNING_COUNT;
if (!of_property_read_u32(np, "marvell,xenon-tun-count",
&tuning_count)) {
if (!device_property_read_u32(dev, "marvell,xenon-tun-count",
&tuning_count)) {
if (unlikely(tuning_count >= XENON_TMR_RETUN_NO_PRESENT)) {
dev_err(mmc_dev(mmc), "Wrong Re-tuning Count. Set default value %d\n",
XENON_DEF_TUNING_COUNT);
@ -444,7 +455,7 @@ static int xenon_probe_dt(struct platform_device *pdev)
}
priv->tuning_count = tuning_count;
return xenon_phy_parse_dt(np, host);
return xenon_phy_parse_params(dev, host);
}
static int xenon_sdhc_prepare(struct sdhci_host *host)
@ -483,6 +494,7 @@ static void xenon_sdhc_unprepare(struct sdhci_host *host)
static int xenon_probe(struct platform_device *pdev)
{
struct sdhci_pltfm_host *pltfm_host;
struct device *dev = &pdev->dev;
struct sdhci_host *host;
struct xenon_priv *priv;
int err;
@ -495,43 +507,47 @@ static int xenon_probe(struct platform_device *pdev)
pltfm_host = sdhci_priv(host);
priv = sdhci_pltfm_priv(pltfm_host);
priv->hw_version = (unsigned long)device_get_match_data(&pdev->dev);
/*
* Link Xenon specific mmc_host_ops function,
* to replace standard ones in sdhci_ops.
*/
xenon_replace_mmc_host_ops(host);
pltfm_host->clk = devm_clk_get(&pdev->dev, "core");
if (IS_ERR(pltfm_host->clk)) {
err = PTR_ERR(pltfm_host->clk);
dev_err(&pdev->dev, "Failed to setup input clk: %d\n", err);
goto free_pltfm;
}
err = clk_prepare_enable(pltfm_host->clk);
if (err)
goto free_pltfm;
priv->axi_clk = devm_clk_get(&pdev->dev, "axi");
if (IS_ERR(priv->axi_clk)) {
err = PTR_ERR(priv->axi_clk);
if (err == -EPROBE_DEFER)
goto err_clk;
} else {
err = clk_prepare_enable(priv->axi_clk);
if (dev->of_node) {
pltfm_host->clk = devm_clk_get(&pdev->dev, "core");
if (IS_ERR(pltfm_host->clk)) {
err = PTR_ERR(pltfm_host->clk);
dev_err(&pdev->dev, "Failed to setup input clk: %d\n", err);
goto free_pltfm;
}
err = clk_prepare_enable(pltfm_host->clk);
if (err)
goto err_clk;
goto free_pltfm;
priv->axi_clk = devm_clk_get(&pdev->dev, "axi");
if (IS_ERR(priv->axi_clk)) {
err = PTR_ERR(priv->axi_clk);
if (err == -EPROBE_DEFER)
goto err_clk;
} else {
err = clk_prepare_enable(priv->axi_clk);
if (err)
goto err_clk;
}
}
err = mmc_of_parse(host->mmc);
if (err)
goto err_clk_axi;
sdhci_get_of_property(pdev);
sdhci_get_property(pdev);
xenon_set_acg(host, false);
/* Xenon specific dt parse */
err = xenon_probe_dt(pdev);
/* Xenon specific parameters parse */
err = xenon_probe_params(pdev);
if (err)
goto err_clk_axi;
@ -667,18 +683,29 @@ static const struct dev_pm_ops sdhci_xenon_dev_pm_ops = {
};
static const struct of_device_id sdhci_xenon_dt_ids[] = {
{ .compatible = "marvell,armada-ap806-sdhci",},
{ .compatible = "marvell,armada-cp110-sdhci",},
{ .compatible = "marvell,armada-3700-sdhci",},
{ .compatible = "marvell,armada-ap806-sdhci", .data = (void *)XENON_AP806},
{ .compatible = "marvell,armada-cp110-sdhci", .data = (void *)XENON_CP110},
{ .compatible = "marvell,armada-3700-sdhci", .data = (void *)XENON_A3700},
{}
};
MODULE_DEVICE_TABLE(of, sdhci_xenon_dt_ids);
#ifdef CONFIG_ACPI
static const struct acpi_device_id sdhci_xenon_acpi_ids[] = {
{ .id = "MRVL0002", XENON_AP806},
{ .id = "MRVL0003", XENON_AP807},
{ .id = "MRVL0004", XENON_CP110},
{}
};
MODULE_DEVICE_TABLE(acpi, sdhci_xenon_acpi_ids);
#endif
static struct platform_driver sdhci_xenon_driver = {
.driver = {
.name = "xenon-sdhci",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = sdhci_xenon_dt_ids,
.acpi_match_table = ACPI_PTR(sdhci_xenon_acpi_ids),
.pm = &sdhci_xenon_dev_pm_ops,
},
.probe = xenon_probe,

View File

@ -53,6 +53,13 @@
#define XENON_CTRL_HS200 0x5
#define XENON_CTRL_HS400 0x6
enum xenon_variant {
XENON_A3700,
XENON_AP806,
XENON_AP807,
XENON_CP110
};
struct xenon_priv {
unsigned char tuning_count;
/* idx of SDHC */
@ -90,11 +97,12 @@ struct xenon_priv {
void *phy_params;
struct xenon_emmc_phy_regs *emmc_phy_regs;
bool restore_needed;
enum xenon_variant hw_version;
};
int xenon_phy_adj(struct sdhci_host *host, struct mmc_ios *ios);
int xenon_phy_parse_dt(struct device_node *np,
struct sdhci_host *host);
int xenon_phy_parse_params(struct device *dev,
struct sdhci_host *host);
void xenon_soc_pad_ctrl(struct sdhci_host *host,
unsigned char signal_voltage);
#endif

View File

@ -3994,10 +3994,10 @@ void __sdhci_read_caps(struct sdhci_host *host, const u16 *ver,
if (host->v4_mode)
sdhci_do_enable_v4_mode(host);
of_property_read_u64(mmc_dev(host->mmc)->of_node,
"sdhci-caps-mask", &dt_caps_mask);
of_property_read_u64(mmc_dev(host->mmc)->of_node,
"sdhci-caps", &dt_caps);
device_property_read_u64(mmc_dev(host->mmc),
"sdhci-caps-mask", &dt_caps_mask);
device_property_read_u64(mmc_dev(host->mmc),
"sdhci-caps", &dt_caps);
v = ver ? *ver : sdhci_readw(host, SDHCI_HOST_VERSION);
host->version = (v & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT;

View File

@ -26,6 +26,7 @@
#include <linux/mmc/sdio.h>
#include <linux/mmc/slot-gpio.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
@ -1515,7 +1516,7 @@ static struct platform_driver sunxi_mmc_driver = {
.driver = {
.name = "sunxi-mmc",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(sunxi_mmc_of_match),
.of_match_table = sunxi_mmc_of_match,
.pm = &sunxi_mmc_pm_ops,
},
.probe = sunxi_mmc_probe,

View File

@ -174,8 +174,7 @@ static int tmio_mmc_probe(struct platform_device *pdev)
if (ret)
goto host_remove;
pr_info("%s at 0x%08lx irq %d\n", mmc_hostname(host->mmc),
(unsigned long)host->ctl, irq);
pr_info("%s at 0x%p irq %d\n", mmc_hostname(host->mmc), host->ctl, irq);
return 0;

View File

@ -42,7 +42,6 @@
#define CTL_DMA_ENABLE 0xd8
#define CTL_RESET_SD 0xe0
#define CTL_VERSION 0xe2
#define CTL_SDIF_MODE 0xe6
/* Definitions for values the CTL_STOP_INTERNAL_ACTION register can take */
#define TMIO_STOP_STP BIT(0)
@ -81,7 +80,11 @@
#define CLK_CTL_SCLKEN BIT(8)
/* Definitions for values the CTL_SD_MEM_CARD_OPT register can take */
#define CARD_OPT_TOP_MASK 0xf0
#define CARD_OPT_TOP_SHIFT 4
#define CARD_OPT_EXTOP BIT(9) /* first appeared on R-Car Gen3 SDHI */
#define CARD_OPT_WIDTH8 BIT(13)
#define CARD_OPT_ALWAYS1 BIT(14)
#define CARD_OPT_WIDTH BIT(15)
/* Definitions for values the CTL_SDIO_STATUS register can take */
@ -180,6 +183,7 @@ struct tmio_mmc_host {
void (*reset)(struct tmio_mmc_host *host);
bool (*check_retune)(struct tmio_mmc_host *host);
void (*fixup_request)(struct tmio_mmc_host *host, struct mmc_request *mrq);
unsigned int (*get_timeout_cycles)(struct tmio_mmc_host *host);
void (*prepare_hs400_tuning)(struct tmio_mmc_host *host);
void (*hs400_downgrade)(struct tmio_mmc_host *host);

View File

@ -796,8 +796,10 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host)
spin_unlock_irqrestore(&host->lock, flags);
if (mrq->cmd->error || (mrq->data && mrq->data->error))
if (mrq->cmd->error || (mrq->data && mrq->data->error)) {
tmio_mmc_ack_mmc_irqs(host, TMIO_MASK_IRQ); /* Clear all */
tmio_mmc_abort_dma(host);
}
/* Error means retune, but executed command was still successful */
if (host->check_retune && host->check_retune(host))
@ -885,6 +887,22 @@ static void tmio_mmc_set_bus_width(struct tmio_mmc_host *host,
sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, reg);
}
static unsigned int tmio_mmc_get_timeout_cycles(struct tmio_mmc_host *host)
{
u16 val = sd_ctrl_read16(host, CTL_SD_MEM_CARD_OPT);
val = (val & CARD_OPT_TOP_MASK) >> CARD_OPT_TOP_SHIFT;
return 1 << (13 + val);
}
static void tmio_mmc_max_busy_timeout(struct tmio_mmc_host *host)
{
unsigned int clk_rate = host->mmc->actual_clock ?: host->mmc->f_max;
host->mmc->max_busy_timeout = host->get_timeout_cycles(host) /
(clk_rate / MSEC_PER_SEC);
}
/* Set MMC clock / power.
* Note: This controller uses a simple divider scheme therefore it cannot
* run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as
@ -943,6 +961,9 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
break;
}
if (host->pdata->flags & TMIO_MMC_USE_BUSY_TIMEOUT)
tmio_mmc_max_busy_timeout(host);
/* Let things settle. delay taken from winCE driver */
usleep_range(140, 200);
if (PTR_ERR(host->mrq) == -EINTR)
@ -1099,6 +1120,9 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host)
if (!(pdata->flags & TMIO_MMC_HAS_IDLE_WAIT))
_host->write16_hook = NULL;
if (pdata->flags & TMIO_MMC_USE_BUSY_TIMEOUT && !_host->get_timeout_cycles)
_host->get_timeout_cycles = tmio_mmc_get_timeout_cycles;
_host->set_pwr = pdata->set_pwr;
ret = tmio_mmc_init_ocr(_host);

View File

@ -586,6 +586,7 @@ static int uniphier_sd_probe(struct platform_device *pdev)
tmio_data = &priv->tmio_data;
tmio_data->flags |= TMIO_MMC_32BIT_DATA_PORT;
tmio_data->flags |= TMIO_MMC_USE_BUSY_TIMEOUT;
host = tmio_mmc_host_alloc(pdev, tmio_data);
if (IS_ERR(host))

View File

@ -266,36 +266,63 @@ EXPORT_SYMBOL(geni_se_init);
static void geni_se_select_fifo_mode(struct geni_se *se)
{
u32 proto = geni_se_read_proto(se);
u32 val;
u32 val, val_old;
geni_se_irq_clear(se);
val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN);
/*
* The RX path for the UART is asynchronous and so needs more
* complex logic for enabling / disabling its interrupts.
*
* Specific notes:
* - The done and TX-related interrupts are managed manually.
* - We don't RX from the main sequencer (we use the secondary) so
* we don't need the RX-related interrupts enabled in the main
* sequencer for UART.
*/
if (proto != GENI_SE_UART) {
val_old = val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN);
val |= M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN;
val |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN;
}
writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN);
if (val != val_old)
writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN);
val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN);
if (proto != GENI_SE_UART)
val_old = val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN);
val |= S_CMD_DONE_EN;
writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN);
if (val != val_old)
writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN);
}
val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);
val_old = val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);
val &= ~GENI_DMA_MODE_EN;
writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN);
if (val != val_old)
writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN);
}
static void geni_se_select_dma_mode(struct geni_se *se)
{
u32 val;
u32 proto = geni_se_read_proto(se);
u32 val, val_old;
geni_se_irq_clear(se);
val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);
if (proto != GENI_SE_UART) {
val_old = val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN);
val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN);
val &= ~(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN);
if (val != val_old)
writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN);
val_old = val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN);
val &= ~S_CMD_DONE_EN;
if (val != val_old)
writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN);
}
val_old = val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);
val |= GENI_DMA_MODE_EN;
writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN);
if (val != val_old)
writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN);
}
/**
@ -651,7 +678,7 @@ int geni_se_tx_dma_prep(struct geni_se *se, void *buf, size_t len,
writel_relaxed(lower_32_bits(*iova), se->base + SE_DMA_TX_PTR_L);
writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_TX_PTR_H);
writel_relaxed(GENI_SE_DMA_EOT_BUF, se->base + SE_DMA_TX_ATTR);
writel_relaxed(len, se->base + SE_DMA_TX_LEN);
writel(len, se->base + SE_DMA_TX_LEN);
return 0;
}
EXPORT_SYMBOL(geni_se_tx_dma_prep);
@ -688,7 +715,7 @@ int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len,
writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_RX_PTR_H);
/* RX does not have EOT buffer type bit. So just reset RX_ATTR */
writel_relaxed(0, se->base + SE_DMA_RX_ATTR);
writel_relaxed(len, se->base + SE_DMA_RX_LEN);
writel(len, se->base + SE_DMA_RX_LEN);
return 0;
}
EXPORT_SYMBOL(geni_se_rx_dma_prep);

View File

@ -55,7 +55,12 @@
*/
#define TMIO_MMC_HAS_IDLE_WAIT BIT(4)
/* BIT(5) is unused */
/*
* Use the busy timeout feature. Probably all TMIO versions support it. Yet,
* we don't have documentation for old variants, so we enable only known good
* variants with this flag. Can be removed once all variants are known good.
*/
#define TMIO_MMC_USE_BUSY_TIMEOUT BIT(5)
/*
* Some controllers have CMD12 automatically

View File

@ -60,6 +60,8 @@ struct mmc_ios {
#define MMC_TIMING_MMC_DDR52 8
#define MMC_TIMING_MMC_HS200 9
#define MMC_TIMING_MMC_HS400 10
#define MMC_TIMING_SD_EXP 11
#define MMC_TIMING_SD_EXP_1_2V 12
unsigned char signal_voltage; /* signalling voltage (1.8V or 3.3V) */
@ -173,6 +175,9 @@ struct mmc_host_ops {
*/
int (*multi_io_quirk)(struct mmc_card *card,
unsigned int direction, int blk_size);
/* Initialize an SD express card, mandatory for MMC_CAP2_SD_EXP. */
int (*init_sd_express)(struct mmc_host *host, struct mmc_ios *ios);
};
struct mmc_cqe_ops {
@ -358,6 +363,8 @@ struct mmc_host {
#define MMC_CAP2_HS200_1_2V_SDR (1 << 6) /* can support */
#define MMC_CAP2_HS200 (MMC_CAP2_HS200_1_8V_SDR | \
MMC_CAP2_HS200_1_2V_SDR)
#define MMC_CAP2_SD_EXP (1 << 7) /* SD express via PCIe */
#define MMC_CAP2_SD_EXP_1_2V (1 << 8) /* SD express 1.2V */
#define MMC_CAP2_CD_ACTIVE_HIGH (1 << 10) /* Card-detect signal active high */
#define MMC_CAP2_RO_ACTIVE_HIGH (1 << 11) /* Write-protect signal active high */
#define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */

View File

@ -82,6 +82,7 @@
#define MS_OC_INT_EN (1 << 23)
#define SD_OC_INT_EN (1 << 22)
#define RTSX_DUM_REG 0x1C
/*
* macros for easy use
@ -658,6 +659,23 @@
#define PM_WAKE_EN 0x01
#define PM_CTRL4 0xFF47
/* FW config info register */
#define RTS5261_FW_CFG_INFO0 0xFF50
#define RTS5261_FW_EXPRESS_TEST_MASK (0x01 << 0)
#define RTS5261_FW_EA_MODE_MASK (0x01 << 5)
#define RTS5261_FW_CFG0 0xFF54
#define RTS5261_FW_ENTER_EXPRESS (0x01 << 0)
#define RTS5261_FW_CFG1 0xFF55
#define RTS5261_SYS_CLK_SEL_MCU_CLK (0x01 << 7)
#define RTS5261_CRC_CLK_SEL_MCU_CLK (0x01 << 6)
#define RTS5261_FAKE_MCU_CLOCK_GATING (0x01 << 5)
#define RTS5261_MCU_BUS_SEL_MASK (0x01 << 4)
#define RTS5261_MCU_CLOCK_SEL_MASK (0x03 << 2)
#define RTS5261_MCU_CLOCK_SEL_16M (0x01 << 2)
#define RTS5261_MCU_CLOCK_GATING (0x01 << 1)
#define RTS5261_DRIVER_ENABLE_FW (0x01 << 0)
#define REG_CFG_OOBS_OFF_TIMER 0xFEA6
#define REG_CFG_OOBS_ON_TIMER 0xFEA7
#define REG_CFG_VCM_ON_TIMER 0xFEA8
@ -701,6 +719,13 @@
#define RTS5260_DVCC_TUNE_MASK 0x70
#define RTS5260_DVCC_33 0x70
/*RTS5261*/
#define RTS5261_LDO1_CFG0 0xFF72
#define RTS5261_LDO1_OCP_THD_MASK (0x07 << 5)
#define RTS5261_LDO1_OCP_EN (0x01 << 4)
#define RTS5261_LDO1_OCP_LMT_THD_MASK (0x03 << 2)
#define RTS5261_LDO1_OCP_LMT_EN (0x01 << 1)
#define LDO_VCC_CFG1 0xFF73
#define LDO_VCC_REF_TUNE_MASK 0x30
#define LDO_VCC_REF_1V2 0x20
@ -741,6 +766,8 @@
#define RTS5260_AUTOLOAD_CFG4 0xFF7F
#define RTS5260_MIMO_DISABLE 0x8A
/*RTS5261*/
#define RTS5261_AUX_CLK_16M_EN (1 << 5)
#define RTS5260_REG_GPIO_CTL0 0xFC1A
#define RTS5260_REG_GPIO_MASK 0x01
@ -1193,6 +1220,7 @@ struct rtsx_pcr {
#define EXTRA_CAPS_MMC_HS200 (1 << 4)
#define EXTRA_CAPS_MMC_8BIT (1 << 5)
#define EXTRA_CAPS_NO_MMC (1 << 7)
#define EXTRA_CAPS_SD_EXPRESS (1 << 8)
u32 extra_caps;
#define IC_VER_A 0
@ -1247,6 +1275,8 @@ struct rtsx_pcr {
#define PCI_PID(pcr) ((pcr)->pci->device)
#define is_version(pcr, pid, ver) \
(CHK_PCI_PID(pcr, pid) && (pcr)->ic_version == (ver))
#define is_version_higher_than(pcr, pid, ver) \
(CHK_PCI_PID(pcr, pid) && (pcr)->ic_version > (ver))
#define pcr_dbg(pcr, fmt, arg...) \
dev_dbg(&(pcr)->pci->dev, fmt, ##arg)