Merge e5f0e38e7e ("Merge tag 'driver-core-6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core") into android-mainline
Steps on the way to 6.12-rc1 Bug: 367265496 Change-Id: Ib569bda9755b5b910b27f8ff620a29d74fe7d375 Signed-off-by: Matthias Maennich <maennich@google.com>
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/arm/cirrus/cirrus,ep9301.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Cirrus Logic EP93xx platforms
|
||||
|
||||
description:
|
||||
The EP93xx SoC is a ARMv4T-based with 200 MHz ARM9 CPU.
|
||||
|
||||
maintainers:
|
||||
- Alexander Sverdlin <alexander.sverdlin@gmail.com>
|
||||
- Nikita Shubin <nikita.shubin@maquefel.me>
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
const: '/'
|
||||
compatible:
|
||||
oneOf:
|
||||
- description: The TS-7250 is a compact, full-featured Single Board
|
||||
Computer (SBC) based upon the Cirrus EP9302 ARM9 CPU
|
||||
items:
|
||||
- const: technologic,ts7250
|
||||
- const: cirrus,ep9301
|
||||
|
||||
- description: The Liebherr BK3 is a derivate from ts7250 board
|
||||
items:
|
||||
- const: liebherr,bk3
|
||||
- const: cirrus,ep9301
|
||||
|
||||
- description: EDB302 is an evaluation board by Cirrus Logic,
|
||||
based on a Cirrus Logic EP9302 CPU
|
||||
items:
|
||||
- const: cirrus,edb9302
|
||||
- const: cirrus,ep9301
|
||||
|
||||
additionalProperties: true
|
||||
@@ -0,0 +1,42 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/ata/cirrus,ep9312-pata.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Cirrus Logic EP9312 PATA controller
|
||||
|
||||
maintainers:
|
||||
- Damien Le Moal <dlemoal@kernel.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: cirrus,ep9312-pata
|
||||
- items:
|
||||
- const: cirrus,ep9315-pata
|
||||
- const: cirrus,ep9312-pata
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
ide@800a0000 {
|
||||
compatible = "cirrus,ep9312-pata";
|
||||
reg = <0x800a0000 0x38>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <8>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&ide_default_pins>;
|
||||
};
|
||||
@@ -0,0 +1,84 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/dma/cirrus,ep9301-dma-m2m.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Cirrus Logic ep93xx SoC DMA controller
|
||||
|
||||
maintainers:
|
||||
- Alexander Sverdlin <alexander.sverdlin@gmail.com>
|
||||
- Nikita Shubin <nikita.shubin@maquefel.me>
|
||||
|
||||
allOf:
|
||||
- $ref: dma-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: cirrus,ep9301-dma-m2m
|
||||
- items:
|
||||
- enum:
|
||||
- cirrus,ep9302-dma-m2m
|
||||
- cirrus,ep9307-dma-m2m
|
||||
- cirrus,ep9312-dma-m2m
|
||||
- cirrus,ep9315-dma-m2m
|
||||
- const: cirrus,ep9301-dma-m2m
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: m2m0 channel registers
|
||||
- description: m2m1 channel registers
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: m2m0 channel gate clock
|
||||
- description: m2m1 channel gate clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: m2m0
|
||||
- const: m2m1
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: m2m0 channel interrupt
|
||||
- description: m2m1 channel interrupt
|
||||
|
||||
'#dma-cells':
|
||||
const: 2
|
||||
description: |
|
||||
The first cell is the unique device channel number as indicated by this
|
||||
table for ep93xx:
|
||||
|
||||
10: SPI controller
|
||||
11: IDE controller
|
||||
|
||||
The second cell is the DMA direction line number:
|
||||
|
||||
1: Memory to device
|
||||
2: Device to memory
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/cirrus,ep9301-syscon.h>
|
||||
dma-controller@80000100 {
|
||||
compatible = "cirrus,ep9301-dma-m2m";
|
||||
reg = <0x80000100 0x0040>,
|
||||
<0x80000140 0x0040>;
|
||||
clocks = <&syscon EP93XX_CLK_M2M0>,
|
||||
<&syscon EP93XX_CLK_M2M1>;
|
||||
clock-names = "m2m0", "m2m1";
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <17>, <18>;
|
||||
#dma-cells = <2>;
|
||||
};
|
||||
@@ -0,0 +1,144 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/dma/cirrus,ep9301-dma-m2p.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Cirrus Logic ep93xx SoC M2P DMA controller
|
||||
|
||||
maintainers:
|
||||
- Alexander Sverdlin <alexander.sverdlin@gmail.com>
|
||||
- Nikita Shubin <nikita.shubin@maquefel.me>
|
||||
|
||||
allOf:
|
||||
- $ref: dma-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: cirrus,ep9301-dma-m2p
|
||||
- items:
|
||||
- enum:
|
||||
- cirrus,ep9302-dma-m2p
|
||||
- cirrus,ep9307-dma-m2p
|
||||
- cirrus,ep9312-dma-m2p
|
||||
- cirrus,ep9315-dma-m2p
|
||||
- const: cirrus,ep9301-dma-m2p
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: m2p0 channel registers
|
||||
- description: m2p1 channel registers
|
||||
- description: m2p2 channel registers
|
||||
- description: m2p3 channel registers
|
||||
- description: m2p4 channel registers
|
||||
- description: m2p5 channel registers
|
||||
- description: m2p6 channel registers
|
||||
- description: m2p7 channel registers
|
||||
- description: m2p8 channel registers
|
||||
- description: m2p9 channel registers
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: m2p0 channel gate clock
|
||||
- description: m2p1 channel gate clock
|
||||
- description: m2p2 channel gate clock
|
||||
- description: m2p3 channel gate clock
|
||||
- description: m2p4 channel gate clock
|
||||
- description: m2p5 channel gate clock
|
||||
- description: m2p6 channel gate clock
|
||||
- description: m2p7 channel gate clock
|
||||
- description: m2p8 channel gate clock
|
||||
- description: m2p9 channel gate clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: m2p0
|
||||
- const: m2p1
|
||||
- const: m2p2
|
||||
- const: m2p3
|
||||
- const: m2p4
|
||||
- const: m2p5
|
||||
- const: m2p6
|
||||
- const: m2p7
|
||||
- const: m2p8
|
||||
- const: m2p9
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: m2p0 channel interrupt
|
||||
- description: m2p1 channel interrupt
|
||||
- description: m2p2 channel interrupt
|
||||
- description: m2p3 channel interrupt
|
||||
- description: m2p4 channel interrupt
|
||||
- description: m2p5 channel interrupt
|
||||
- description: m2p6 channel interrupt
|
||||
- description: m2p7 channel interrupt
|
||||
- description: m2p8 channel interrupt
|
||||
- description: m2p9 channel interrupt
|
||||
|
||||
'#dma-cells':
|
||||
const: 2
|
||||
description: |
|
||||
The first cell is the unique device channel number as indicated by this
|
||||
table for ep93xx:
|
||||
|
||||
0: I2S channel 1
|
||||
1: I2S channel 2 (unused)
|
||||
2: AC97 channel 1 (unused)
|
||||
3: AC97 channel 2 (unused)
|
||||
4: AC97 channel 3 (unused)
|
||||
5: I2S channel 3 (unused)
|
||||
6: UART1 (unused)
|
||||
7: UART2 (unused)
|
||||
8: UART3 (unused)
|
||||
9: IRDA (unused)
|
||||
|
||||
The second cell is the DMA direction line number:
|
||||
|
||||
1: Memory to device
|
||||
2: Device to memory
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/cirrus,ep9301-syscon.h>
|
||||
dma-controller@80000000 {
|
||||
compatible = "cirrus,ep9301-dma-m2p";
|
||||
reg = <0x80000000 0x0040>,
|
||||
<0x80000040 0x0040>,
|
||||
<0x80000080 0x0040>,
|
||||
<0x800000c0 0x0040>,
|
||||
<0x80000240 0x0040>,
|
||||
<0x80000200 0x0040>,
|
||||
<0x800002c0 0x0040>,
|
||||
<0x80000280 0x0040>,
|
||||
<0x80000340 0x0040>,
|
||||
<0x80000300 0x0040>;
|
||||
clocks = <&syscon EP93XX_CLK_M2P0>,
|
||||
<&syscon EP93XX_CLK_M2P1>,
|
||||
<&syscon EP93XX_CLK_M2P2>,
|
||||
<&syscon EP93XX_CLK_M2P3>,
|
||||
<&syscon EP93XX_CLK_M2P4>,
|
||||
<&syscon EP93XX_CLK_M2P5>,
|
||||
<&syscon EP93XX_CLK_M2P6>,
|
||||
<&syscon EP93XX_CLK_M2P7>,
|
||||
<&syscon EP93XX_CLK_M2P8>,
|
||||
<&syscon EP93XX_CLK_M2P9>;
|
||||
clock-names = "m2p0", "m2p1",
|
||||
"m2p2", "m2p3",
|
||||
"m2p4", "m2p5",
|
||||
"m2p6", "m2p7",
|
||||
"m2p8", "m2p9";
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <7>, <8>, <9>, <10>, <11>, <12>, <13>, <14>, <15>, <16>;
|
||||
#dma-cells = <2>;
|
||||
};
|
||||
@@ -73,9 +73,10 @@ examples:
|
||||
reg-names = "data", "dir", "intr";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <27>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <27>;
|
||||
};
|
||||
|
||||
gpio@80840004 {
|
||||
@@ -87,6 +88,7 @@ examples:
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <27>;
|
||||
};
|
||||
@@ -127,6 +129,7 @@ examples:
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts-extended = <&vic0 19>, <&vic0 20>,
|
||||
<&vic0 21>, <&vic0 22>,
|
||||
<&vic1 15>, <&vic1 16>,
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/cirrus,ep9307-keypad.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Cirrus ep93xx keypad
|
||||
|
||||
maintainers:
|
||||
- Alexander Sverdlin <alexander.sverdlin@gmail.com>
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/input/matrix-keymap.yaml#
|
||||
|
||||
description:
|
||||
The KPP is designed to interface with a keypad matrix with 2-point contact
|
||||
or 3-point contact keys. The KPP is designed to simplify the software task
|
||||
of scanning a keypad matrix. The KPP is capable of detecting, debouncing,
|
||||
and decoding one or multiple keys pressed simultaneously on a keypad.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: cirrus,ep9307-keypad
|
||||
- items:
|
||||
- enum:
|
||||
- cirrus,ep9312-keypad
|
||||
- cirrus,ep9315-keypad
|
||||
- const: cirrus,ep9307-keypad
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
debounce-delay-ms:
|
||||
description: |
|
||||
Time in microseconds that key must be pressed or
|
||||
released for state change interrupt to trigger.
|
||||
|
||||
cirrus,prescale:
|
||||
description: row/column counter pre-scaler load value
|
||||
$ref: /schemas/types.yaml#/definitions/uint16
|
||||
maximum: 1023
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- linux,keymap
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/clock/cirrus,ep9301-syscon.h>
|
||||
keypad@800f0000 {
|
||||
compatible = "cirrus,ep9307-keypad";
|
||||
reg = <0x800f0000 0x0c>;
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <29>;
|
||||
clocks = <&eclk EP93XX_CLK_KEYPAD>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&keypad_default_pins>;
|
||||
linux,keymap = <KEY_UP>,
|
||||
<KEY_DOWN>,
|
||||
<KEY_VOLUMEDOWN>,
|
||||
<KEY_HOME>,
|
||||
<KEY_RIGHT>,
|
||||
<KEY_LEFT>,
|
||||
<KEY_ENTER>,
|
||||
<KEY_VOLUMEUP>,
|
||||
<KEY_F6>,
|
||||
<KEY_F8>,
|
||||
<KEY_F9>,
|
||||
<KEY_F10>,
|
||||
<KEY_F1>,
|
||||
<KEY_F2>,
|
||||
<KEY_F3>,
|
||||
<KEY_POWER>;
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mtd/technologic,nand.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Technologic Systems NAND controller
|
||||
|
||||
maintainers:
|
||||
- Nikita Shubin <nikita.shubin@maquefel.me>
|
||||
|
||||
allOf:
|
||||
- $ref: nand-controller.yaml
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: technologic,ts7200-nand
|
||||
- items:
|
||||
- enum:
|
||||
- technologic,ts7300-nand
|
||||
- technologic,ts7260-nand
|
||||
- technologic,ts7250-nand
|
||||
- const: technologic,ts7200-nand
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
nand-controller@60000000 {
|
||||
compatible = "technologic,ts7200-nand";
|
||||
reg = <0x60000000 0x8000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
nand@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/cirrus,ep9301-eth.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: EP93xx SoC Ethernet Controller
|
||||
|
||||
maintainers:
|
||||
- Alexander Sverdlin <alexander.sverdlin@gmail.com>
|
||||
- Nikita Shubin <nikita.shubin@maquefel.me>
|
||||
|
||||
allOf:
|
||||
- $ref: ethernet-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: cirrus,ep9301-eth
|
||||
- items:
|
||||
- enum:
|
||||
- cirrus,ep9302-eth
|
||||
- cirrus,ep9307-eth
|
||||
- cirrus,ep9312-eth
|
||||
- cirrus,ep9315-eth
|
||||
- const: cirrus,ep9301-eth
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: The physical base address and size of IO range
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: Combined signal for various interrupt events
|
||||
|
||||
phy-handle: true
|
||||
|
||||
mdio:
|
||||
$ref: mdio.yaml#
|
||||
unevaluatedProperties: false
|
||||
description: optional node for embedded MDIO controller
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- phy-handle
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
ethernet@80010000 {
|
||||
compatible = "cirrus,ep9301-eth";
|
||||
reg = <0x80010000 0x10000>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <7>;
|
||||
phy-handle = <&phy0>;
|
||||
};
|
||||
@@ -0,0 +1,53 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/pwm/cirrus,ep9301-pwm.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Cirrus Logic ep93xx PWM controller
|
||||
|
||||
maintainers:
|
||||
- Alexander Sverdlin <alexander.sverdlin@gmail.com>
|
||||
- Nikita Shubin <nikita.shubin@maquefel.me>
|
||||
|
||||
allOf:
|
||||
- $ref: pwm.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: cirrus,ep9301-pwm
|
||||
- items:
|
||||
- enum:
|
||||
- cirrus,ep9302-pwm
|
||||
- cirrus,ep9307-pwm
|
||||
- cirrus,ep9312-pwm
|
||||
- cirrus,ep9315-pwm
|
||||
- const: cirrus,ep9301-pwm
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: SoC PWM clock
|
||||
|
||||
"#pwm-cells":
|
||||
const: 3
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/cirrus,ep9301-syscon.h>
|
||||
pwm@80910000 {
|
||||
compatible = "cirrus,ep9301-pwm";
|
||||
reg = <0x80910000 0x10>;
|
||||
clocks = <&syscon EP93XX_CLK_PWM>;
|
||||
#pwm-cells = <3>;
|
||||
};
|
||||
@@ -0,0 +1,94 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/soc/cirrus/cirrus,ep9301-syscon.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Cirrus Logic EP93xx Platforms System Controller
|
||||
|
||||
maintainers:
|
||||
- Alexander Sverdlin <alexander.sverdlin@gmail.com>
|
||||
- Nikita Shubin <nikita.shubin@maquefel.me>
|
||||
|
||||
description: |
|
||||
Central resources are controlled by a set of software-locked registers,
|
||||
which can be used to prevent accidental accesses. Syscon generates
|
||||
the various bus and peripheral clocks and controls the system startup
|
||||
configuration.
|
||||
|
||||
The System Controller (Syscon) provides:
|
||||
- Clock control
|
||||
- Power management
|
||||
- System configuration management
|
||||
|
||||
Syscon registers are common for all EP93xx SoC's, through some actual peripheral
|
||||
may be missing depending on actual SoC model.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- cirrus,ep9302-syscon
|
||||
- cirrus,ep9307-syscon
|
||||
- cirrus,ep9312-syscon
|
||||
- cirrus,ep9315-syscon
|
||||
- const: cirrus,ep9301-syscon
|
||||
- const: syscon
|
||||
- items:
|
||||
- const: cirrus,ep9301-syscon
|
||||
- const: syscon
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#clock-cells":
|
||||
const: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: reference clock
|
||||
|
||||
patternProperties:
|
||||
'^pins-':
|
||||
type: object
|
||||
description: pin node
|
||||
$ref: /schemas/pinctrl/pinmux-node.yaml
|
||||
|
||||
properties:
|
||||
function:
|
||||
enum: [ spi, ac97, i2s, pwm, keypad, pata, lcd, gpio ]
|
||||
|
||||
groups:
|
||||
enum: [ ssp, ac97, i2s_on_ssp, i2s_on_ac97, pwm1, gpio1agrp,
|
||||
gpio2agrp, gpio3agrp, gpio4agrp, gpio6agrp, gpio7agrp,
|
||||
rasteronsdram0grp, rasteronsdram3grp, keypadgrp, idegrp ]
|
||||
|
||||
required:
|
||||
- function
|
||||
- groups
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#clock-cells"
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
syscon@80930000 {
|
||||
compatible = "cirrus,ep9301-syscon", "syscon";
|
||||
reg = <0x80930000 0x1000>;
|
||||
|
||||
#clock-cells = <1>;
|
||||
clocks = <&xtali>;
|
||||
|
||||
spi_default_pins: pins-spi {
|
||||
function = "spi";
|
||||
groups = "ssp";
|
||||
};
|
||||
};
|
||||
@@ -40,6 +40,20 @@ properties:
|
||||
- const: sclk
|
||||
- const: lrclk
|
||||
|
||||
dmas:
|
||||
items:
|
||||
- description: out DMA channel
|
||||
- description: in DMA channel
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: tx
|
||||
- const: rx
|
||||
|
||||
port:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- '#sound-dai-cells'
|
||||
@@ -61,6 +75,8 @@ examples:
|
||||
<&syscon 30>,
|
||||
<&syscon 31>;
|
||||
clock-names = "mclk", "sclk", "lrclk";
|
||||
dmas = <&dma0 0 1>, <&dma0 0 2>;
|
||||
dma-names = "tx", "rx";
|
||||
};
|
||||
|
||||
...
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/spi/cirrus,ep9301-spi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: EP93xx SoC SPI controller
|
||||
|
||||
maintainers:
|
||||
- Alexander Sverdlin <alexander.sverdlin@gmail.com>
|
||||
- Nikita Shubin <nikita.shubin@maquefel.me>
|
||||
|
||||
allOf:
|
||||
- $ref: spi-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: cirrus,ep9301-spi
|
||||
- items:
|
||||
- enum:
|
||||
- cirrus,ep9302-spi
|
||||
- cirrus,ep9307-spi
|
||||
- cirrus,ep9312-spi
|
||||
- cirrus,ep9315-spi
|
||||
- const: cirrus,ep9301-spi
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: SPI registers region
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: SPI Controller reference clock source
|
||||
|
||||
dmas:
|
||||
items:
|
||||
- description: rx DMA channel
|
||||
- description: tx DMA channel
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: rx
|
||||
- const: tx
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/clock/cirrus,ep9301-syscon.h>
|
||||
spi@808a0000 {
|
||||
compatible = "cirrus,ep9301-spi";
|
||||
reg = <0x808a0000 0x18>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <21>;
|
||||
clocks = <&syscon EP93XX_CLK_SPI>;
|
||||
dmas = <&dma1 10 2>, <&dma1 10 1>;
|
||||
dma-names = "rx", "tx";
|
||||
cs-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
@@ -75,7 +75,6 @@ Example conversion::
|
||||
|
||||
-static const struct file_operations s3c2410wdt_fops = {
|
||||
- .owner = THIS_MODULE,
|
||||
- .llseek = no_llseek,
|
||||
- .write = s3c2410wdt_write,
|
||||
- .unlocked_ioctl = s3c2410wdt_ioctl,
|
||||
- .open = s3c2410wdt_open,
|
||||
|
||||
@@ -2272,6 +2272,7 @@ N: clps711x
|
||||
ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE
|
||||
M: Hartley Sweeten <hsweeten@visionengravers.com>
|
||||
M: Alexander Sverdlin <alexander.sverdlin@gmail.com>
|
||||
M: Nikita Shubin <nikita.shubin@maquefel.me>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/adc/cirrus,ep9301-adc.yaml
|
||||
|
||||
@@ -3,17 +3,232 @@
|
||||
#define _ALPHA_CMPXCHG_H
|
||||
|
||||
/*
|
||||
* Atomic exchange routines.
|
||||
* Atomic exchange.
|
||||
* Since it can be used to implement critical sections
|
||||
* it must clobber "memory" (also for interrupts in UP).
|
||||
*/
|
||||
|
||||
#define ____xchg(type, args...) __arch_xchg ## type ## _local(args)
|
||||
#define ____cmpxchg(type, args...) __cmpxchg ## type ## _local(args)
|
||||
#include <asm/xchg.h>
|
||||
static inline unsigned long
|
||||
____xchg_u8(volatile char *m, unsigned long val)
|
||||
{
|
||||
unsigned long ret, tmp, addr64;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" andnot %4,7,%3\n"
|
||||
" insbl %1,%4,%1\n"
|
||||
"1: ldq_l %2,0(%3)\n"
|
||||
" extbl %2,%4,%0\n"
|
||||
" mskbl %2,%4,%2\n"
|
||||
" or %1,%2,%2\n"
|
||||
" stq_c %2,0(%3)\n"
|
||||
" beq %2,2f\n"
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64)
|
||||
: "r" ((long)m), "1" (val) : "memory");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____xchg_u16(volatile short *m, unsigned long val)
|
||||
{
|
||||
unsigned long ret, tmp, addr64;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" andnot %4,7,%3\n"
|
||||
" inswl %1,%4,%1\n"
|
||||
"1: ldq_l %2,0(%3)\n"
|
||||
" extwl %2,%4,%0\n"
|
||||
" mskwl %2,%4,%2\n"
|
||||
" or %1,%2,%2\n"
|
||||
" stq_c %2,0(%3)\n"
|
||||
" beq %2,2f\n"
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64)
|
||||
: "r" ((long)m), "1" (val) : "memory");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____xchg_u32(volatile int *m, unsigned long val)
|
||||
{
|
||||
unsigned long dummy;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldl_l %0,%4\n"
|
||||
" bis $31,%3,%1\n"
|
||||
" stl_c %1,%2\n"
|
||||
" beq %1,2f\n"
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (val), "=&r" (dummy), "=m" (*m)
|
||||
: "rI" (val), "m" (*m) : "memory");
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____xchg_u64(volatile long *m, unsigned long val)
|
||||
{
|
||||
unsigned long dummy;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldq_l %0,%4\n"
|
||||
" bis $31,%3,%1\n"
|
||||
" stq_c %1,%2\n"
|
||||
" beq %1,2f\n"
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (val), "=&r" (dummy), "=m" (*m)
|
||||
: "rI" (val), "m" (*m) : "memory");
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/* This function doesn't exist, so you'll get a linker error
|
||||
if something tries to do an invalid xchg(). */
|
||||
extern void __xchg_called_with_bad_pointer(void);
|
||||
|
||||
static __always_inline unsigned long
|
||||
____xchg(volatile void *ptr, unsigned long x, int size)
|
||||
{
|
||||
return
|
||||
size == 1 ? ____xchg_u8(ptr, x) :
|
||||
size == 2 ? ____xchg_u16(ptr, x) :
|
||||
size == 4 ? ____xchg_u32(ptr, x) :
|
||||
size == 8 ? ____xchg_u64(ptr, x) :
|
||||
(__xchg_called_with_bad_pointer(), x);
|
||||
}
|
||||
|
||||
/*
|
||||
* Atomic compare and exchange. Compare OLD with MEM, if identical,
|
||||
* store NEW in MEM. Return the initial value in MEM. Success is
|
||||
* indicated by comparing RETURN with OLD.
|
||||
*/
|
||||
|
||||
static inline unsigned long
|
||||
____cmpxchg_u8(volatile char *m, unsigned char old, unsigned char new)
|
||||
{
|
||||
unsigned long prev, tmp, cmp, addr64;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" andnot %5,7,%4\n"
|
||||
" insbl %1,%5,%1\n"
|
||||
"1: ldq_l %2,0(%4)\n"
|
||||
" extbl %2,%5,%0\n"
|
||||
" cmpeq %0,%6,%3\n"
|
||||
" beq %3,2f\n"
|
||||
" mskbl %2,%5,%2\n"
|
||||
" or %1,%2,%2\n"
|
||||
" stq_c %2,0(%4)\n"
|
||||
" beq %2,3f\n"
|
||||
"2:\n"
|
||||
".subsection 2\n"
|
||||
"3: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64)
|
||||
: "r" ((long)m), "Ir" (old), "1" (new) : "memory");
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____cmpxchg_u16(volatile short *m, unsigned short old, unsigned short new)
|
||||
{
|
||||
unsigned long prev, tmp, cmp, addr64;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" andnot %5,7,%4\n"
|
||||
" inswl %1,%5,%1\n"
|
||||
"1: ldq_l %2,0(%4)\n"
|
||||
" extwl %2,%5,%0\n"
|
||||
" cmpeq %0,%6,%3\n"
|
||||
" beq %3,2f\n"
|
||||
" mskwl %2,%5,%2\n"
|
||||
" or %1,%2,%2\n"
|
||||
" stq_c %2,0(%4)\n"
|
||||
" beq %2,3f\n"
|
||||
"2:\n"
|
||||
".subsection 2\n"
|
||||
"3: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64)
|
||||
: "r" ((long)m), "Ir" (old), "1" (new) : "memory");
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____cmpxchg_u32(volatile int *m, int old, int new)
|
||||
{
|
||||
unsigned long prev, cmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldl_l %0,%5\n"
|
||||
" cmpeq %0,%3,%1\n"
|
||||
" beq %1,2f\n"
|
||||
" mov %4,%1\n"
|
||||
" stl_c %1,%2\n"
|
||||
" beq %1,3f\n"
|
||||
"2:\n"
|
||||
".subsection 2\n"
|
||||
"3: br 1b\n"
|
||||
".previous"
|
||||
: "=&r"(prev), "=&r"(cmp), "=m"(*m)
|
||||
: "r"((long) old), "r"(new), "m"(*m) : "memory");
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
|
||||
{
|
||||
unsigned long prev, cmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldq_l %0,%5\n"
|
||||
" cmpeq %0,%3,%1\n"
|
||||
" beq %1,2f\n"
|
||||
" mov %4,%1\n"
|
||||
" stq_c %1,%2\n"
|
||||
" beq %1,3f\n"
|
||||
"2:\n"
|
||||
".subsection 2\n"
|
||||
"3: br 1b\n"
|
||||
".previous"
|
||||
: "=&r"(prev), "=&r"(cmp), "=m"(*m)
|
||||
: "r"((long) old), "r"(new), "m"(*m) : "memory");
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
/* This function doesn't exist, so you'll get a linker error
|
||||
if something tries to do an invalid cmpxchg(). */
|
||||
extern void __cmpxchg_called_with_bad_pointer(void);
|
||||
|
||||
static __always_inline unsigned long
|
||||
____cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
|
||||
int size)
|
||||
{
|
||||
return
|
||||
size == 1 ? ____cmpxchg_u8(ptr, old, new) :
|
||||
size == 2 ? ____cmpxchg_u16(ptr, old, new) :
|
||||
size == 4 ? ____cmpxchg_u32(ptr, old, new) :
|
||||
size == 8 ? ____cmpxchg_u64(ptr, old, new) :
|
||||
(__cmpxchg_called_with_bad_pointer(), old);
|
||||
}
|
||||
|
||||
#define xchg_local(ptr, x) \
|
||||
({ \
|
||||
__typeof__(*(ptr)) _x_ = (x); \
|
||||
(__typeof__(*(ptr))) __arch_xchg_local((ptr), (unsigned long)_x_,\
|
||||
(__typeof__(*(ptr))) ____xchg((ptr), (unsigned long)_x_, \
|
||||
sizeof(*(ptr))); \
|
||||
})
|
||||
|
||||
@@ -21,7 +236,7 @@
|
||||
({ \
|
||||
__typeof__(*(ptr)) _o_ = (o); \
|
||||
__typeof__(*(ptr)) _n_ = (n); \
|
||||
(__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_, \
|
||||
(__typeof__(*(ptr))) ____cmpxchg((ptr), (unsigned long)_o_, \
|
||||
(unsigned long)_n_, \
|
||||
sizeof(*(ptr))); \
|
||||
})
|
||||
@@ -32,12 +247,6 @@
|
||||
cmpxchg_local((ptr), (o), (n)); \
|
||||
})
|
||||
|
||||
#undef ____xchg
|
||||
#undef ____cmpxchg
|
||||
#define ____xchg(type, args...) __arch_xchg ##type(args)
|
||||
#define ____cmpxchg(type, args...) __cmpxchg ##type(args)
|
||||
#include <asm/xchg.h>
|
||||
|
||||
/*
|
||||
* The leading and the trailing memory barriers guarantee that these
|
||||
* operations are fully ordered.
|
||||
@@ -48,7 +257,7 @@
|
||||
__typeof__(*(ptr)) _x_ = (x); \
|
||||
smp_mb(); \
|
||||
__ret = (__typeof__(*(ptr))) \
|
||||
__arch_xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \
|
||||
____xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \
|
||||
smp_mb(); \
|
||||
__ret; \
|
||||
})
|
||||
@@ -59,7 +268,7 @@
|
||||
__typeof__(*(ptr)) _o_ = (o); \
|
||||
__typeof__(*(ptr)) _n_ = (n); \
|
||||
smp_mb(); \
|
||||
__ret = (__typeof__(*(ptr))) __cmpxchg((ptr), \
|
||||
__ret = (__typeof__(*(ptr))) ____cmpxchg((ptr), \
|
||||
(unsigned long)_o_, (unsigned long)_n_, sizeof(*(ptr)));\
|
||||
smp_mb(); \
|
||||
__ret; \
|
||||
@@ -71,6 +280,4 @@
|
||||
arch_cmpxchg((ptr), (o), (n)); \
|
||||
})
|
||||
|
||||
#undef ____cmpxchg
|
||||
|
||||
#endif /* _ALPHA_CMPXCHG_H */
|
||||
|
||||
@@ -1,246 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ALPHA_CMPXCHG_H
|
||||
#error Do not include xchg.h directly!
|
||||
#else
|
||||
/*
|
||||
* xchg/xchg_local and cmpxchg/cmpxchg_local share the same code
|
||||
* except that local version do not have the expensive memory barrier.
|
||||
* So this file is included twice from asm/cmpxchg.h.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Atomic exchange.
|
||||
* Since it can be used to implement critical sections
|
||||
* it must clobber "memory" (also for interrupts in UP).
|
||||
*/
|
||||
|
||||
static inline unsigned long
|
||||
____xchg(_u8, volatile char *m, unsigned long val)
|
||||
{
|
||||
unsigned long ret, tmp, addr64;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" andnot %4,7,%3\n"
|
||||
" insbl %1,%4,%1\n"
|
||||
"1: ldq_l %2,0(%3)\n"
|
||||
" extbl %2,%4,%0\n"
|
||||
" mskbl %2,%4,%2\n"
|
||||
" or %1,%2,%2\n"
|
||||
" stq_c %2,0(%3)\n"
|
||||
" beq %2,2f\n"
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64)
|
||||
: "r" ((long)m), "1" (val) : "memory");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____xchg(_u16, volatile short *m, unsigned long val)
|
||||
{
|
||||
unsigned long ret, tmp, addr64;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" andnot %4,7,%3\n"
|
||||
" inswl %1,%4,%1\n"
|
||||
"1: ldq_l %2,0(%3)\n"
|
||||
" extwl %2,%4,%0\n"
|
||||
" mskwl %2,%4,%2\n"
|
||||
" or %1,%2,%2\n"
|
||||
" stq_c %2,0(%3)\n"
|
||||
" beq %2,2f\n"
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64)
|
||||
: "r" ((long)m), "1" (val) : "memory");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____xchg(_u32, volatile int *m, unsigned long val)
|
||||
{
|
||||
unsigned long dummy;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldl_l %0,%4\n"
|
||||
" bis $31,%3,%1\n"
|
||||
" stl_c %1,%2\n"
|
||||
" beq %1,2f\n"
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (val), "=&r" (dummy), "=m" (*m)
|
||||
: "rI" (val), "m" (*m) : "memory");
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____xchg(_u64, volatile long *m, unsigned long val)
|
||||
{
|
||||
unsigned long dummy;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldq_l %0,%4\n"
|
||||
" bis $31,%3,%1\n"
|
||||
" stq_c %1,%2\n"
|
||||
" beq %1,2f\n"
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (val), "=&r" (dummy), "=m" (*m)
|
||||
: "rI" (val), "m" (*m) : "memory");
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/* This function doesn't exist, so you'll get a linker error
|
||||
if something tries to do an invalid xchg(). */
|
||||
extern void __xchg_called_with_bad_pointer(void);
|
||||
|
||||
static __always_inline unsigned long
|
||||
____xchg(, volatile void *ptr, unsigned long x, int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 1:
|
||||
return ____xchg(_u8, ptr, x);
|
||||
case 2:
|
||||
return ____xchg(_u16, ptr, x);
|
||||
case 4:
|
||||
return ____xchg(_u32, ptr, x);
|
||||
case 8:
|
||||
return ____xchg(_u64, ptr, x);
|
||||
}
|
||||
__xchg_called_with_bad_pointer();
|
||||
return x;
|
||||
}
|
||||
|
||||
/*
|
||||
* Atomic compare and exchange. Compare OLD with MEM, if identical,
|
||||
* store NEW in MEM. Return the initial value in MEM. Success is
|
||||
* indicated by comparing RETURN with OLD.
|
||||
*/
|
||||
|
||||
static inline unsigned long
|
||||
____cmpxchg(_u8, volatile char *m, unsigned char old, unsigned char new)
|
||||
{
|
||||
unsigned long prev, tmp, cmp, addr64;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" andnot %5,7,%4\n"
|
||||
" insbl %1,%5,%1\n"
|
||||
"1: ldq_l %2,0(%4)\n"
|
||||
" extbl %2,%5,%0\n"
|
||||
" cmpeq %0,%6,%3\n"
|
||||
" beq %3,2f\n"
|
||||
" mskbl %2,%5,%2\n"
|
||||
" or %1,%2,%2\n"
|
||||
" stq_c %2,0(%4)\n"
|
||||
" beq %2,3f\n"
|
||||
"2:\n"
|
||||
".subsection 2\n"
|
||||
"3: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64)
|
||||
: "r" ((long)m), "Ir" (old), "1" (new) : "memory");
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____cmpxchg(_u16, volatile short *m, unsigned short old, unsigned short new)
|
||||
{
|
||||
unsigned long prev, tmp, cmp, addr64;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" andnot %5,7,%4\n"
|
||||
" inswl %1,%5,%1\n"
|
||||
"1: ldq_l %2,0(%4)\n"
|
||||
" extwl %2,%5,%0\n"
|
||||
" cmpeq %0,%6,%3\n"
|
||||
" beq %3,2f\n"
|
||||
" mskwl %2,%5,%2\n"
|
||||
" or %1,%2,%2\n"
|
||||
" stq_c %2,0(%4)\n"
|
||||
" beq %2,3f\n"
|
||||
"2:\n"
|
||||
".subsection 2\n"
|
||||
"3: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64)
|
||||
: "r" ((long)m), "Ir" (old), "1" (new) : "memory");
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____cmpxchg(_u32, volatile int *m, int old, int new)
|
||||
{
|
||||
unsigned long prev, cmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldl_l %0,%5\n"
|
||||
" cmpeq %0,%3,%1\n"
|
||||
" beq %1,2f\n"
|
||||
" mov %4,%1\n"
|
||||
" stl_c %1,%2\n"
|
||||
" beq %1,3f\n"
|
||||
"2:\n"
|
||||
".subsection 2\n"
|
||||
"3: br 1b\n"
|
||||
".previous"
|
||||
: "=&r"(prev), "=&r"(cmp), "=m"(*m)
|
||||
: "r"((long) old), "r"(new), "m"(*m) : "memory");
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____cmpxchg(_u64, volatile long *m, unsigned long old, unsigned long new)
|
||||
{
|
||||
unsigned long prev, cmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldq_l %0,%5\n"
|
||||
" cmpeq %0,%3,%1\n"
|
||||
" beq %1,2f\n"
|
||||
" mov %4,%1\n"
|
||||
" stq_c %1,%2\n"
|
||||
" beq %1,3f\n"
|
||||
"2:\n"
|
||||
".subsection 2\n"
|
||||
"3: br 1b\n"
|
||||
".previous"
|
||||
: "=&r"(prev), "=&r"(cmp), "=m"(*m)
|
||||
: "r"((long) old), "r"(new), "m"(*m) : "memory");
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
/* This function doesn't exist, so you'll get a linker error
|
||||
if something tries to do an invalid cmpxchg(). */
|
||||
extern void __cmpxchg_called_with_bad_pointer(void);
|
||||
|
||||
static __always_inline unsigned long
|
||||
____cmpxchg(, volatile void *ptr, unsigned long old, unsigned long new,
|
||||
int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 1:
|
||||
return ____cmpxchg(_u8, ptr, old, new);
|
||||
case 2:
|
||||
return ____cmpxchg(_u16, ptr, old, new);
|
||||
case 4:
|
||||
return ____cmpxchg(_u32, ptr, old, new);
|
||||
case 8:
|
||||
return ____cmpxchg(_u64, ptr, old, new);
|
||||
}
|
||||
__cmpxchg_called_with_bad_pointer();
|
||||
return old;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -183,7 +183,6 @@ machine-$(CONFIG_ARCH_CLPS711X) += clps711x
|
||||
machine-$(CONFIG_ARCH_DAVINCI) += davinci
|
||||
machine-$(CONFIG_ARCH_DIGICOLOR) += digicolor
|
||||
machine-$(CONFIG_ARCH_DOVE) += dove
|
||||
machine-$(CONFIG_ARCH_EP93XX) += ep93xx
|
||||
machine-$(CONFIG_ARCH_EXYNOS) += exynos
|
||||
machine-$(CONFIG_ARCH_FOOTBRIDGE) += footbridge
|
||||
machine-$(CONFIG_ARCH_GEMINI) += gemini
|
||||
|
||||
@@ -3,3 +3,7 @@ dtb-$(CONFIG_ARCH_CLPS711X) += \
|
||||
ep7211-edb7211.dtb
|
||||
dtb-$(CONFIG_ARCH_CLPS711X) += \
|
||||
ep7211-edb7211.dtb
|
||||
dtb-$(CONFIG_ARCH_EP93XX) += \
|
||||
ep93xx-edb9302.dtb \
|
||||
ep93xx-bk3.dtb \
|
||||
ep93xx-ts7250.dtb
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Device Tree file for Liebherr controller BK3.1 based on Cirrus EP9302 SoC
|
||||
*/
|
||||
/dts-v1/;
|
||||
#include "ep93xx.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Liebherr controller BK3.1";
|
||||
compatible = "liebherr,bk3", "cirrus,ep9301";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
chosen {
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
/* should be set from ATAGS */
|
||||
reg = <0x00000000 0x02000000>,
|
||||
<0x000530c0 0x01fdd000>;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
led-0 {
|
||||
label = "grled";
|
||||
gpios = <&gpio4 0 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "heartbeat";
|
||||
function = LED_FUNCTION_HEARTBEAT;
|
||||
};
|
||||
|
||||
led-1 {
|
||||
label = "rdled";
|
||||
gpios = <&gpio4 1 GPIO_ACTIVE_HIGH>;
|
||||
function = LED_FUNCTION_FAULT;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&ebi {
|
||||
nand-controller@60000000 {
|
||||
compatible = "technologic,ts7200-nand";
|
||||
reg = <0x60000000 0x8000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
nand@0 {
|
||||
reg = <0>;
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "System";
|
||||
reg = <0x00000000 0x01e00000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@1e00000 {
|
||||
label = "Data";
|
||||
reg = <0x01e00000 0x05f20000>;
|
||||
};
|
||||
|
||||
partition@7d20000 {
|
||||
label = "RedBoot";
|
||||
reg = <0x07d20000 0x002e0000>;
|
||||
read-only;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ð0 {
|
||||
phy-handle = <&phy0>;
|
||||
};
|
||||
|
||||
&i2s {
|
||||
dmas = <&dma0 0 1>, <&dma0 0 2>;
|
||||
dma-names = "tx", "rx";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2s_on_ac97_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
/* PWM */
|
||||
gpio-ranges = <&syscon 6 163 1>;
|
||||
};
|
||||
|
||||
&gpio4 {
|
||||
gpio-ranges = <&syscon 0 97 2>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio6 {
|
||||
gpio-ranges = <&syscon 0 87 2>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio7 {
|
||||
gpio-ranges = <&syscon 2 199 4>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mdio0 {
|
||||
phy0: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
device_type = "ethernet-phy";
|
||||
};
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usb0 {
|
||||
status = "okay";
|
||||
};
|
||||
@@ -0,0 +1,181 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
/*
|
||||
* Device Tree file for Cirrus Logic EDB9302 board based on EP9302 SoC
|
||||
*/
|
||||
/dts-v1/;
|
||||
#include "ep93xx.dtsi"
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "cirrus,edb9302", "cirrus,ep9301";
|
||||
model = "cirrus,edb9302";
|
||||
|
||||
chosen {
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
/* should be set from ATAGS */
|
||||
reg = <0x0000000 0x800000>,
|
||||
<0x1000000 0x800000>,
|
||||
<0x4000000 0x800000>,
|
||||
<0x5000000 0x800000>;
|
||||
};
|
||||
|
||||
sound {
|
||||
compatible = "audio-graph-card2";
|
||||
label = "EDB93XX";
|
||||
links = <&i2s_port>;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
led-0 {
|
||||
label = "grled";
|
||||
gpios = <&gpio4 0 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "heartbeat";
|
||||
function = LED_FUNCTION_HEARTBEAT;
|
||||
};
|
||||
|
||||
led-1 {
|
||||
label = "rdled";
|
||||
gpios = <&gpio4 1 GPIO_ACTIVE_HIGH>;
|
||||
function = LED_FUNCTION_FAULT;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&adc {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&ebi {
|
||||
flash@60000000 {
|
||||
compatible = "cfi-flash";
|
||||
reg = <0x60000000 0x1000000>;
|
||||
bank-width = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
ð0 {
|
||||
phy-handle = <&phy0>;
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
gpio-ranges = <&syscon 0 153 1>,
|
||||
<&syscon 1 152 1>,
|
||||
<&syscon 2 151 1>,
|
||||
<&syscon 3 148 1>,
|
||||
<&syscon 4 147 1>,
|
||||
<&syscon 5 146 1>,
|
||||
<&syscon 6 145 1>,
|
||||
<&syscon 7 144 1>;
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
gpio-ranges = <&syscon 0 143 1>,
|
||||
<&syscon 1 142 1>,
|
||||
<&syscon 2 141 1>,
|
||||
<&syscon 3 140 1>,
|
||||
<&syscon 4 165 1>,
|
||||
<&syscon 5 164 1>,
|
||||
<&syscon 6 163 1>,
|
||||
<&syscon 7 160 1>;
|
||||
};
|
||||
|
||||
&gpio2 {
|
||||
gpio-ranges = <&syscon 0 115 1>;
|
||||
};
|
||||
|
||||
/* edb9302 doesn't have GPIO Port D present */
|
||||
&gpio3 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&gpio4 {
|
||||
gpio-ranges = <&syscon 0 97 2>;
|
||||
};
|
||||
|
||||
&gpio5 {
|
||||
gpio-ranges = <&syscon 1 170 1>,
|
||||
<&syscon 2 169 1>,
|
||||
<&syscon 3 168 1>;
|
||||
};
|
||||
|
||||
&gpio6 {
|
||||
gpio-ranges = <&syscon 0 87 2>;
|
||||
};
|
||||
|
||||
&gpio7 {
|
||||
gpio-ranges = <&syscon 2 199 4>;
|
||||
};
|
||||
|
||||
&i2s {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2s_on_ac97_pins>;
|
||||
status = "okay";
|
||||
i2s_port: port {
|
||||
i2s_ep: endpoint {
|
||||
system-clock-direction-out;
|
||||
frame-master;
|
||||
bitclock-master;
|
||||
mclk-fs = <256>;
|
||||
dai-format = "i2s";
|
||||
convert-channels = <2>;
|
||||
convert-sample-format = "s32_le";
|
||||
remote-endpoint = <&codec_ep>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&mdio0 {
|
||||
phy0: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
device_type = "ethernet-phy";
|
||||
};
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
cs-gpios = <&gpio0 6 GPIO_ACTIVE_LOW
|
||||
&gpio0 7 GPIO_ACTIVE_LOW>;
|
||||
dmas = <&dma1 10 2>, <&dma1 10 1>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "okay";
|
||||
|
||||
cs4271: codec@0 {
|
||||
compatible = "cirrus,cs4271";
|
||||
reg = <0>;
|
||||
#sound-dai-cells = <0>;
|
||||
spi-max-frequency = <6000000>;
|
||||
spi-cpol;
|
||||
spi-cpha;
|
||||
reset-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
|
||||
port {
|
||||
codec_ep: endpoint {
|
||||
remote-endpoint = <&i2s_ep>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
at25f1024: eeprom@1 {
|
||||
compatible = "atmel,at25";
|
||||
reg = <1>;
|
||||
address-width = <8>;
|
||||
size = <0x20000>;
|
||||
pagesize = <256>;
|
||||
spi-max-frequency = <20000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usb0 {
|
||||
status = "okay";
|
||||
};
|
||||
@@ -0,0 +1,145 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Device Tree file for Technologic Systems ts7250 board based on Cirrus EP9302 SoC
|
||||
*/
|
||||
/dts-v1/;
|
||||
#include "ep93xx.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "technologic,ts7250", "cirrus,ep9301";
|
||||
model = "TS-7250 SBC";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
chosen {
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
/* should be set from ATAGS */
|
||||
reg = <0x00000000 0x02000000>,
|
||||
<0x000530c0 0x01fdd000>;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
led-0 {
|
||||
label = "grled";
|
||||
gpios = <&gpio4 0 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "heartbeat";
|
||||
function = LED_FUNCTION_HEARTBEAT;
|
||||
};
|
||||
|
||||
led-1 {
|
||||
label = "rdled";
|
||||
gpios = <&gpio4 1 GPIO_ACTIVE_HIGH>;
|
||||
function = LED_FUNCTION_FAULT;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&ebi {
|
||||
nand-controller@60000000 {
|
||||
compatible = "technologic,ts7200-nand";
|
||||
reg = <0x60000000 0x8000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
nand@0 {
|
||||
reg = <0>;
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "TS-BOOTROM";
|
||||
reg = <0x00000000 0x00020000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@20000 {
|
||||
label = "Linux";
|
||||
reg = <0x00020000 0x07d00000>;
|
||||
};
|
||||
|
||||
partition@7d20000 {
|
||||
label = "RedBoot";
|
||||
reg = <0x07d20000 0x002e0000>;
|
||||
read-only;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
rtc@10800000 {
|
||||
compatible = "st,m48t86";
|
||||
reg = <0x10800000 0x1>,
|
||||
<0x11700000 0x1>;
|
||||
};
|
||||
|
||||
watchdog@23800000 {
|
||||
compatible = "technologic,ts7200-wdt";
|
||||
reg = <0x23800000 0x01>,
|
||||
<0x23c00000 0x01>;
|
||||
timeout-sec = <30>;
|
||||
};
|
||||
};
|
||||
|
||||
ð0 {
|
||||
phy-handle = <&phy0>;
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
/* PWM */
|
||||
gpio-ranges = <&syscon 6 163 1>;
|
||||
};
|
||||
|
||||
/* ts7250 doesn't have GPIO Port D present */
|
||||
&gpio3 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&gpio4 {
|
||||
gpio-ranges = <&syscon 0 97 2>;
|
||||
};
|
||||
|
||||
&gpio6 {
|
||||
gpio-ranges = <&syscon 0 87 2>;
|
||||
};
|
||||
|
||||
&gpio7 {
|
||||
gpio-ranges = <&syscon 2 199 4>;
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
cs-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;
|
||||
dmas = <&dma1 10 2>, <&dma1 10 1>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "okay";
|
||||
|
||||
tmp122: temperature-sensor@0 {
|
||||
compatible = "ti,tmp122";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <2000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&mdio0 {
|
||||
phy0: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
device_type = "ethernet-phy";
|
||||
};
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usb0 {
|
||||
status = "okay";
|
||||
};
|
||||
@@ -0,0 +1,444 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Device Tree file for Cirrus Logic systems EP93XX SoC
|
||||
*/
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/clock/cirrus,ep9301-syscon.h>
|
||||
/ {
|
||||
soc: soc {
|
||||
compatible = "simple-bus";
|
||||
ranges;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
syscon: syscon@80930000 {
|
||||
compatible = "cirrus,ep9301-syscon", "syscon";
|
||||
reg = <0x80930000 0x1000>;
|
||||
|
||||
#clock-cells = <1>;
|
||||
clocks = <&xtali>;
|
||||
|
||||
spi_default_pins: pins-spi {
|
||||
function = "spi";
|
||||
groups = "ssp";
|
||||
};
|
||||
|
||||
ac97_default_pins: pins-ac97 {
|
||||
function = "ac97";
|
||||
groups = "ac97";
|
||||
};
|
||||
|
||||
i2s_on_ssp_pins: pins-i2sonssp {
|
||||
function = "i2s";
|
||||
groups = "i2s_on_ssp";
|
||||
};
|
||||
|
||||
i2s_on_ac97_pins: pins-i2sonac97 {
|
||||
function = "i2s";
|
||||
groups = "i2s_on_ac97";
|
||||
};
|
||||
|
||||
gpio1_default_pins: pins-gpio1 {
|
||||
function = "gpio";
|
||||
groups = "gpio1agrp";
|
||||
};
|
||||
|
||||
pwm1_default_pins: pins-pwm1 {
|
||||
function = "pwm";
|
||||
groups = "pwm1";
|
||||
};
|
||||
|
||||
gpio2_default_pins: pins-gpio2 {
|
||||
function = "gpio";
|
||||
groups = "gpio2agrp";
|
||||
};
|
||||
|
||||
gpio3_default_pins: pins-gpio3 {
|
||||
function = "gpio";
|
||||
groups = "gpio3agrp";
|
||||
};
|
||||
|
||||
keypad_default_pins: pins-keypad {
|
||||
function = "keypad";
|
||||
groups = "keypadgrp";
|
||||
};
|
||||
|
||||
gpio4_default_pins: pins-gpio4 {
|
||||
function = "gpio";
|
||||
groups = "gpio4agrp";
|
||||
};
|
||||
|
||||
gpio6_default_pins: pins-gpio6 {
|
||||
function = "gpio";
|
||||
groups = "gpio6agrp";
|
||||
};
|
||||
|
||||
gpio7_default_pins: pins-gpio7 {
|
||||
function = "gpio";
|
||||
groups = "gpio7agrp";
|
||||
};
|
||||
|
||||
ide_default_pins: pins-ide {
|
||||
function = "pata";
|
||||
groups = "idegrp";
|
||||
};
|
||||
|
||||
lcd_on_dram0_pins: pins-rasteronsdram0 {
|
||||
function = "lcd";
|
||||
groups = "rasteronsdram0grp";
|
||||
};
|
||||
|
||||
lcd_on_dram3_pins: pins-rasteronsdram3 {
|
||||
function = "lcd";
|
||||
groups = "rasteronsdram3grp";
|
||||
};
|
||||
};
|
||||
|
||||
adc: adc@80900000 {
|
||||
compatible = "cirrus,ep9301-adc";
|
||||
reg = <0x80900000 0x28>;
|
||||
clocks = <&syscon EP93XX_CLK_ADC>;
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <30>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
/*
|
||||
* The EP93XX expansion bus is a set of up to 7 each up to 16MB
|
||||
* windows in the 256MB space from 0x50000000 to 0x5fffffff.
|
||||
* But since we don't require to setup it in any way, we can
|
||||
* represent it as a simple-bus.
|
||||
*/
|
||||
ebi: bus@80080000 {
|
||||
compatible = "simple-bus";
|
||||
reg = <0x80080000 0x20>;
|
||||
native-endian;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
};
|
||||
|
||||
dma0: dma-controller@80000000 {
|
||||
compatible = "cirrus,ep9301-dma-m2p";
|
||||
reg = <0x80000000 0x0040>,
|
||||
<0x80000040 0x0040>,
|
||||
<0x80000080 0x0040>,
|
||||
<0x800000c0 0x0040>,
|
||||
<0x80000240 0x0040>,
|
||||
<0x80000200 0x0040>,
|
||||
<0x800002c0 0x0040>,
|
||||
<0x80000280 0x0040>,
|
||||
<0x80000340 0x0040>,
|
||||
<0x80000300 0x0040>;
|
||||
clocks = <&syscon EP93XX_CLK_M2P0>,
|
||||
<&syscon EP93XX_CLK_M2P1>,
|
||||
<&syscon EP93XX_CLK_M2P2>,
|
||||
<&syscon EP93XX_CLK_M2P3>,
|
||||
<&syscon EP93XX_CLK_M2P4>,
|
||||
<&syscon EP93XX_CLK_M2P5>,
|
||||
<&syscon EP93XX_CLK_M2P6>,
|
||||
<&syscon EP93XX_CLK_M2P7>,
|
||||
<&syscon EP93XX_CLK_M2P8>,
|
||||
<&syscon EP93XX_CLK_M2P9>;
|
||||
clock-names = "m2p0", "m2p1",
|
||||
"m2p2", "m2p3",
|
||||
"m2p4", "m2p5",
|
||||
"m2p6", "m2p7",
|
||||
"m2p8", "m2p9";
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <7>, <8>, <9>, <10>, <11>,
|
||||
<12>, <13>, <14>, <15>, <16>;
|
||||
#dma-cells = <2>;
|
||||
};
|
||||
|
||||
dma1: dma-controller@80000100 {
|
||||
compatible = "cirrus,ep9301-dma-m2m";
|
||||
reg = <0x80000100 0x0040>,
|
||||
<0x80000140 0x0040>;
|
||||
clocks = <&syscon EP93XX_CLK_M2M0>,
|
||||
<&syscon EP93XX_CLK_M2M1>;
|
||||
clock-names = "m2m0", "m2m1";
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <17>, <18>;
|
||||
#dma-cells = <2>;
|
||||
};
|
||||
|
||||
eth0: ethernet@80010000 {
|
||||
compatible = "cirrus,ep9301-eth";
|
||||
reg = <0x80010000 0x10000>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <7>;
|
||||
mdio0: mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio0: gpio@80840000 {
|
||||
compatible = "cirrus,ep9301-gpio";
|
||||
reg = <0x80840000 0x04>,
|
||||
<0x80840010 0x04>,
|
||||
<0x80840090 0x1c>;
|
||||
reg-names = "data", "dir", "intr";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <27>;
|
||||
};
|
||||
|
||||
gpio1: gpio@80840004 {
|
||||
compatible = "cirrus,ep9301-gpio";
|
||||
reg = <0x80840004 0x04>,
|
||||
<0x80840014 0x04>,
|
||||
<0x808400ac 0x1c>;
|
||||
reg-names = "data", "dir", "intr";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <27>;
|
||||
};
|
||||
|
||||
gpio2: gpio@80840008 {
|
||||
compatible = "cirrus,ep9301-gpio";
|
||||
reg = <0x80840008 0x04>,
|
||||
<0x80840018 0x04>;
|
||||
reg-names = "data", "dir";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&gpio2_default_pins>;
|
||||
};
|
||||
|
||||
gpio3: gpio@8084000c {
|
||||
compatible = "cirrus,ep9301-gpio";
|
||||
reg = <0x8084000c 0x04>,
|
||||
<0x8084001c 0x04>;
|
||||
reg-names = "data", "dir";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&gpio3_default_pins>;
|
||||
};
|
||||
|
||||
gpio4: gpio@80840020 {
|
||||
compatible = "cirrus,ep9301-gpio";
|
||||
reg = <0x80840020 0x04>,
|
||||
<0x80840024 0x04>;
|
||||
reg-names = "data", "dir";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&gpio4_default_pins>;
|
||||
};
|
||||
|
||||
gpio5: gpio@80840030 {
|
||||
compatible = "cirrus,ep9301-gpio";
|
||||
reg = <0x80840030 0x04>,
|
||||
<0x80840034 0x04>,
|
||||
<0x8084004c 0x1c>;
|
||||
reg-names = "data", "dir", "intr";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts-extended = <&vic0 19>, <&vic0 20>,
|
||||
<&vic0 21>, <&vic0 22>,
|
||||
<&vic1 15>, <&vic1 16>,
|
||||
<&vic1 17>, <&vic1 18>;
|
||||
};
|
||||
|
||||
gpio6: gpio@80840038 {
|
||||
compatible = "cirrus,ep9301-gpio";
|
||||
reg = <0x80840038 0x04>,
|
||||
<0x8084003c 0x04>;
|
||||
reg-names = "data", "dir";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&gpio6_default_pins>;
|
||||
};
|
||||
|
||||
gpio7: gpio@80840040 {
|
||||
compatible = "cirrus,ep9301-gpio";
|
||||
reg = <0x80840040 0x04>,
|
||||
<0x80840044 0x04>;
|
||||
reg-names = "data", "dir";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&gpio7_default_pins>;
|
||||
};
|
||||
|
||||
i2s: i2s@80820000 {
|
||||
compatible = "cirrus,ep9301-i2s";
|
||||
reg = <0x80820000 0x100>;
|
||||
#sound-dai-cells = <0>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <28>;
|
||||
clocks = <&syscon EP93XX_CLK_I2S_MCLK>,
|
||||
<&syscon EP93XX_CLK_I2S_SCLK>,
|
||||
<&syscon EP93XX_CLK_I2S_LRCLK>;
|
||||
clock-names = "mclk", "sclk", "lrclk";
|
||||
dmas = <&dma0 0 1>, <&dma0 0 2>;
|
||||
dma-names = "tx", "rx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
ide: ide@800a0000 {
|
||||
compatible = "cirrus,ep9312-pata";
|
||||
reg = <0x800a0000 0x38>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <8>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&ide_default_pins>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
vic0: interrupt-controller@800b0000 {
|
||||
compatible = "arm,pl192-vic";
|
||||
reg = <0x800b0000 0x1000>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
valid-mask = <0x7ffffffc>;
|
||||
valid-wakeup-mask = <0x0>;
|
||||
};
|
||||
|
||||
vic1: interrupt-controller@800c0000 {
|
||||
compatible = "arm,pl192-vic";
|
||||
reg = <0x800c0000 0x1000>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
valid-mask = <0x1fffffff>;
|
||||
valid-wakeup-mask = <0x0>;
|
||||
};
|
||||
|
||||
keypad: keypad@800f0000 {
|
||||
compatible = "cirrus,ep9307-keypad";
|
||||
reg = <0x800f0000 0x0c>;
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <29>;
|
||||
clocks = <&syscon EP93XX_CLK_KEYPAD>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&keypad_default_pins>;
|
||||
linux,keymap = <KEY_UP>,
|
||||
<KEY_DOWN>,
|
||||
<KEY_VOLUMEDOWN>,
|
||||
<KEY_HOME>,
|
||||
<KEY_RIGHT>,
|
||||
<KEY_LEFT>,
|
||||
<KEY_ENTER>,
|
||||
<KEY_VOLUMEUP>,
|
||||
<KEY_F6>,
|
||||
<KEY_F8>,
|
||||
<KEY_F9>,
|
||||
<KEY_F10>,
|
||||
<KEY_F1>,
|
||||
<KEY_F2>,
|
||||
<KEY_F3>,
|
||||
<KEY_POWER>;
|
||||
};
|
||||
|
||||
pwm0: pwm@80910000 {
|
||||
compatible = "cirrus,ep9301-pwm";
|
||||
reg = <0x80910000 0x10>;
|
||||
clocks = <&syscon EP93XX_CLK_PWM>;
|
||||
#pwm-cells = <3>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pwm1: pwm@80910020 {
|
||||
compatible = "cirrus,ep9301-pwm";
|
||||
reg = <0x80910020 0x10>;
|
||||
clocks = <&syscon EP93XX_CLK_PWM>;
|
||||
#pwm-cells = <3>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pwm1_default_pins>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
rtc0: rtc@80920000 {
|
||||
compatible = "cirrus,ep9301-rtc";
|
||||
reg = <0x80920000 0x100>;
|
||||
};
|
||||
|
||||
spi0: spi@808a0000 {
|
||||
compatible = "cirrus,ep9301-spi";
|
||||
reg = <0x808a0000 0x18>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <21>;
|
||||
clocks = <&syscon EP93XX_CLK_SPI>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&spi_default_pins>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
timer: timer@80810000 {
|
||||
compatible = "cirrus,ep9301-timer";
|
||||
reg = <0x80810000 0x100>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <19>;
|
||||
};
|
||||
|
||||
uart0: serial@808c0000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0x808c0000 0x1000>;
|
||||
arm,primecell-periphid = <0x00041010>;
|
||||
clocks = <&syscon EP93XX_CLK_UART1>, <&syscon EP93XX_CLK_UART>;
|
||||
clock-names = "uartclk", "apb_pclk";
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <20>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uart1: uart@808d0000 {
|
||||
compatible = "arm,primecell";
|
||||
reg = <0x808d0000 0x1000>;
|
||||
arm,primecell-periphid = <0x00041010>;
|
||||
clocks = <&syscon EP93XX_CLK_UART2>, <&syscon EP93XX_CLK_UART>;
|
||||
clock-names = "apb:uart2", "apb_pclk";
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <22>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uart2: uart@808b0000 {
|
||||
compatible = "arm,primecell";
|
||||
reg = <0x808b0000 0x1000>;
|
||||
arm,primecell-periphid = <0x00041010>;
|
||||
clocks = <&syscon EP93XX_CLK_UART3>, <&syscon EP93XX_CLK_UART>;
|
||||
clock-names = "apb:uart3", "apb_pclk";
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <23>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usb0: usb@80020000 {
|
||||
compatible = "generic-ohci";
|
||||
reg = <0x80020000 0x10000>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <24>;
|
||||
clocks = <&syscon EP93XX_CLK_USB>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
watchdog0: watchdog@80940000 {
|
||||
compatible = "cirrus,ep9301-wdt";
|
||||
reg = <0x80940000 0x08>;
|
||||
};
|
||||
};
|
||||
|
||||
xtali: oscillator {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <14745600>;
|
||||
clock-output-names = "xtali";
|
||||
};
|
||||
};
|
||||
@@ -3,27 +3,27 @@ menuconfig ARCH_EP93XX
|
||||
bool "EP93xx-based"
|
||||
depends on ATAGS
|
||||
depends on ARCH_MULTI_V4T
|
||||
# CONFIG_ARCH_MULTI_V7 is not set
|
||||
depends on CPU_LITTLE_ENDIAN
|
||||
select ARCH_HAS_RESET_CONTROLLER
|
||||
select ARCH_SPARSEMEM_ENABLE
|
||||
select ARM_AMBA
|
||||
select ARM_VIC
|
||||
select ARM_APPENDED_DTB # Old Redboot bootloaders deployed
|
||||
select ARM_ATAG_DTB_COMPAT # we need this to update dt memory node
|
||||
select COMMON_CLK_EP93XX
|
||||
select EP93XX_TIMER
|
||||
select CLKSRC_MMIO
|
||||
select CPU_ARM920T
|
||||
select GPIOLIB
|
||||
select PINCTRL
|
||||
select PINCTRL_EP93XX
|
||||
help
|
||||
This enables support for the Cirrus EP93xx series of CPUs.
|
||||
|
||||
if ARCH_EP93XX
|
||||
|
||||
menu "Cirrus EP93xx Implementation Options"
|
||||
|
||||
config EP93XX_SOC_COMMON
|
||||
bool
|
||||
default y
|
||||
select SOC_BUS
|
||||
select LEDS_GPIO_REGISTER
|
||||
|
||||
comment "EP93xx Platforms"
|
||||
# menu "EP93xx Platforms"
|
||||
|
||||
config MACH_BK3
|
||||
bool "Support Liebherr BK3.1"
|
||||
@@ -103,6 +103,6 @@ config MACH_VISION_EP9307
|
||||
Say 'Y' here if you want your kernel to support the
|
||||
Vision Engraving Systems EP9307 SoM.
|
||||
|
||||
endmenu
|
||||
# endmenu
|
||||
|
||||
endif
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Makefile for the linux kernel.
|
||||
#
|
||||
obj-y := core.o clock.o timer-ep93xx.o
|
||||
|
||||
obj-$(CONFIG_EP93XX_DMA) += dma.o
|
||||
|
||||
obj-$(CONFIG_MACH_EDB93XX) += edb93xx.o
|
||||
obj-$(CONFIG_MACH_TS72XX) += ts72xx.o
|
||||
obj-$(CONFIG_MACH_VISION_EP9307)+= vision_ep9307.o
|
||||
@@ -1,733 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* arch/arm/mach-ep93xx/clock.c
|
||||
* Clock control for Cirrus EP93xx chips.
|
||||
*
|
||||
* Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/soc/cirrus/ep93xx.h>
|
||||
|
||||
#include "hardware.h"
|
||||
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include "soc.h"
|
||||
|
||||
static DEFINE_SPINLOCK(clk_lock);
|
||||
|
||||
static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
|
||||
static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
|
||||
static char pclk_divisors[] = { 1, 2, 4, 8 };
|
||||
|
||||
static char adc_divisors[] = { 16, 4 };
|
||||
static char sclk_divisors[] = { 2, 4 };
|
||||
static char lrclk_divisors[] = { 32, 64, 128 };
|
||||
|
||||
static const char * const mux_parents[] = {
|
||||
"xtali",
|
||||
"pll1",
|
||||
"pll2"
|
||||
};
|
||||
|
||||
/*
|
||||
* PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS
|
||||
*/
|
||||
static unsigned long calc_pll_rate(unsigned long long rate, u32 config_word)
|
||||
{
|
||||
int i;
|
||||
|
||||
rate *= ((config_word >> 11) & 0x1f) + 1; /* X1FBD */
|
||||
rate *= ((config_word >> 5) & 0x3f) + 1; /* X2FBD */
|
||||
do_div(rate, (config_word & 0x1f) + 1); /* X2IPD */
|
||||
for (i = 0; i < ((config_word >> 16) & 3); i++) /* PS */
|
||||
rate >>= 1;
|
||||
|
||||
return (unsigned long)rate;
|
||||
}
|
||||
|
||||
struct clk_psc {
|
||||
struct clk_hw hw;
|
||||
void __iomem *reg;
|
||||
u8 bit_idx;
|
||||
u32 mask;
|
||||
u8 shift;
|
||||
u8 width;
|
||||
char *div;
|
||||
u8 num_div;
|
||||
spinlock_t *lock;
|
||||
};
|
||||
|
||||
#define to_clk_psc(_hw) container_of(_hw, struct clk_psc, hw)
|
||||
|
||||
static int ep93xx_clk_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_psc *psc = to_clk_psc(hw);
|
||||
u32 val = readl(psc->reg);
|
||||
|
||||
return (val & BIT(psc->bit_idx)) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int ep93xx_clk_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_psc *psc = to_clk_psc(hw);
|
||||
unsigned long flags = 0;
|
||||
u32 val;
|
||||
|
||||
if (psc->lock)
|
||||
spin_lock_irqsave(psc->lock, flags);
|
||||
|
||||
val = __raw_readl(psc->reg);
|
||||
val |= BIT(psc->bit_idx);
|
||||
|
||||
ep93xx_syscon_swlocked_write(val, psc->reg);
|
||||
|
||||
if (psc->lock)
|
||||
spin_unlock_irqrestore(psc->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ep93xx_clk_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_psc *psc = to_clk_psc(hw);
|
||||
unsigned long flags = 0;
|
||||
u32 val;
|
||||
|
||||
if (psc->lock)
|
||||
spin_lock_irqsave(psc->lock, flags);
|
||||
|
||||
val = __raw_readl(psc->reg);
|
||||
val &= ~BIT(psc->bit_idx);
|
||||
|
||||
ep93xx_syscon_swlocked_write(val, psc->reg);
|
||||
|
||||
if (psc->lock)
|
||||
spin_unlock_irqrestore(psc->lock, flags);
|
||||
}
|
||||
|
||||
static const struct clk_ops clk_ep93xx_gate_ops = {
|
||||
.enable = ep93xx_clk_enable,
|
||||
.disable = ep93xx_clk_disable,
|
||||
.is_enabled = ep93xx_clk_is_enabled,
|
||||
};
|
||||
|
||||
static struct clk_hw *ep93xx_clk_register_gate(const char *name,
|
||||
const char *parent_name,
|
||||
void __iomem *reg,
|
||||
u8 bit_idx)
|
||||
{
|
||||
struct clk_init_data init;
|
||||
struct clk_psc *psc;
|
||||
struct clk *clk;
|
||||
|
||||
psc = kzalloc(sizeof(*psc), GFP_KERNEL);
|
||||
if (!psc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &clk_ep93xx_gate_ops;
|
||||
init.flags = CLK_SET_RATE_PARENT;
|
||||
init.parent_names = (parent_name ? &parent_name : NULL);
|
||||
init.num_parents = (parent_name ? 1 : 0);
|
||||
|
||||
psc->reg = reg;
|
||||
psc->bit_idx = bit_idx;
|
||||
psc->hw.init = &init;
|
||||
psc->lock = &clk_lock;
|
||||
|
||||
clk = clk_register(NULL, &psc->hw);
|
||||
if (IS_ERR(clk)) {
|
||||
kfree(psc);
|
||||
return ERR_CAST(clk);
|
||||
}
|
||||
|
||||
return &psc->hw;
|
||||
}
|
||||
|
||||
static u8 ep93xx_mux_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_psc *psc = to_clk_psc(hw);
|
||||
u32 val = __raw_readl(psc->reg);
|
||||
|
||||
if (!(val & EP93XX_SYSCON_CLKDIV_ESEL))
|
||||
return 0;
|
||||
|
||||
if (!(val & EP93XX_SYSCON_CLKDIV_PSEL))
|
||||
return 1;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int ep93xx_mux_set_parent_lock(struct clk_hw *hw, u8 index)
|
||||
{
|
||||
struct clk_psc *psc = to_clk_psc(hw);
|
||||
unsigned long flags = 0;
|
||||
u32 val;
|
||||
|
||||
if (index >= ARRAY_SIZE(mux_parents))
|
||||
return -EINVAL;
|
||||
|
||||
if (psc->lock)
|
||||
spin_lock_irqsave(psc->lock, flags);
|
||||
|
||||
val = __raw_readl(psc->reg);
|
||||
val &= ~(EP93XX_SYSCON_CLKDIV_ESEL | EP93XX_SYSCON_CLKDIV_PSEL);
|
||||
|
||||
|
||||
if (index != 0) {
|
||||
val |= EP93XX_SYSCON_CLKDIV_ESEL;
|
||||
val |= (index - 1) ? EP93XX_SYSCON_CLKDIV_PSEL : 0;
|
||||
}
|
||||
|
||||
ep93xx_syscon_swlocked_write(val, psc->reg);
|
||||
|
||||
if (psc->lock)
|
||||
spin_unlock_irqrestore(psc->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool is_best(unsigned long rate, unsigned long now,
|
||||
unsigned long best)
|
||||
{
|
||||
return abs(rate - now) < abs(rate - best);
|
||||
}
|
||||
|
||||
static int ep93xx_mux_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
unsigned long rate = req->rate;
|
||||
struct clk *best_parent = NULL;
|
||||
unsigned long __parent_rate;
|
||||
unsigned long best_rate = 0, actual_rate, mclk_rate;
|
||||
unsigned long best_parent_rate;
|
||||
int __div = 0, __pdiv = 0;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Try the two pll's and the external clock
|
||||
* Because the valid predividers are 2, 2.5 and 3, we multiply
|
||||
* all the clocks by 2 to avoid floating point math.
|
||||
*
|
||||
* This is based on the algorithm in the ep93xx raster guide:
|
||||
* http://be-a-maverick.com/en/pubs/appNote/AN269REV1.pdf
|
||||
*
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(mux_parents); i++) {
|
||||
struct clk *parent = clk_get_sys(mux_parents[i], NULL);
|
||||
|
||||
__parent_rate = clk_get_rate(parent);
|
||||
mclk_rate = __parent_rate * 2;
|
||||
|
||||
/* Try each predivider value */
|
||||
for (__pdiv = 4; __pdiv <= 6; __pdiv++) {
|
||||
__div = mclk_rate / (rate * __pdiv);
|
||||
if (__div < 2 || __div > 127)
|
||||
continue;
|
||||
|
||||
actual_rate = mclk_rate / (__pdiv * __div);
|
||||
if (is_best(rate, actual_rate, best_rate)) {
|
||||
best_rate = actual_rate;
|
||||
best_parent_rate = __parent_rate;
|
||||
best_parent = parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!best_parent)
|
||||
return -EINVAL;
|
||||
|
||||
req->best_parent_rate = best_parent_rate;
|
||||
req->best_parent_hw = __clk_get_hw(best_parent);
|
||||
req->rate = best_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long ep93xx_ddiv_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_psc *psc = to_clk_psc(hw);
|
||||
unsigned long rate = 0;
|
||||
u32 val = __raw_readl(psc->reg);
|
||||
int __pdiv = ((val >> EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) & 0x03);
|
||||
int __div = val & 0x7f;
|
||||
|
||||
if (__div > 0)
|
||||
rate = (parent_rate * 2) / ((__pdiv + 3) * __div);
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static int ep93xx_ddiv_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_psc *psc = to_clk_psc(hw);
|
||||
int pdiv = 0, div = 0;
|
||||
unsigned long best_rate = 0, actual_rate, mclk_rate;
|
||||
int __div = 0, __pdiv = 0;
|
||||
u32 val;
|
||||
|
||||
mclk_rate = parent_rate * 2;
|
||||
|
||||
for (__pdiv = 4; __pdiv <= 6; __pdiv++) {
|
||||
__div = mclk_rate / (rate * __pdiv);
|
||||
if (__div < 2 || __div > 127)
|
||||
continue;
|
||||
|
||||
actual_rate = mclk_rate / (__pdiv * __div);
|
||||
if (is_best(rate, actual_rate, best_rate)) {
|
||||
pdiv = __pdiv - 3;
|
||||
div = __div;
|
||||
best_rate = actual_rate;
|
||||
}
|
||||
}
|
||||
|
||||
if (!best_rate)
|
||||
return -EINVAL;
|
||||
|
||||
val = __raw_readl(psc->reg);
|
||||
|
||||
/* Clear old dividers */
|
||||
val &= ~0x37f;
|
||||
|
||||
/* Set the new pdiv and div bits for the new clock rate */
|
||||
val |= (pdiv << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | div;
|
||||
ep93xx_syscon_swlocked_write(val, psc->reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops clk_ddiv_ops = {
|
||||
.enable = ep93xx_clk_enable,
|
||||
.disable = ep93xx_clk_disable,
|
||||
.is_enabled = ep93xx_clk_is_enabled,
|
||||
.get_parent = ep93xx_mux_get_parent,
|
||||
.set_parent = ep93xx_mux_set_parent_lock,
|
||||
.determine_rate = ep93xx_mux_determine_rate,
|
||||
.recalc_rate = ep93xx_ddiv_recalc_rate,
|
||||
.set_rate = ep93xx_ddiv_set_rate,
|
||||
};
|
||||
|
||||
static struct clk_hw *clk_hw_register_ddiv(const char *name,
|
||||
void __iomem *reg,
|
||||
u8 bit_idx)
|
||||
{
|
||||
struct clk_init_data init;
|
||||
struct clk_psc *psc;
|
||||
struct clk *clk;
|
||||
|
||||
psc = kzalloc(sizeof(*psc), GFP_KERNEL);
|
||||
if (!psc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &clk_ddiv_ops;
|
||||
init.flags = 0;
|
||||
init.parent_names = mux_parents;
|
||||
init.num_parents = ARRAY_SIZE(mux_parents);
|
||||
|
||||
psc->reg = reg;
|
||||
psc->bit_idx = bit_idx;
|
||||
psc->lock = &clk_lock;
|
||||
psc->hw.init = &init;
|
||||
|
||||
clk = clk_register(NULL, &psc->hw);
|
||||
if (IS_ERR(clk)) {
|
||||
kfree(psc);
|
||||
return ERR_CAST(clk);
|
||||
}
|
||||
return &psc->hw;
|
||||
}
|
||||
|
||||
static unsigned long ep93xx_div_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_psc *psc = to_clk_psc(hw);
|
||||
u32 val = __raw_readl(psc->reg);
|
||||
u8 index = (val & psc->mask) >> psc->shift;
|
||||
|
||||
if (index > psc->num_div)
|
||||
return 0;
|
||||
|
||||
return DIV_ROUND_UP_ULL(parent_rate, psc->div[index]);
|
||||
}
|
||||
|
||||
static long ep93xx_div_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
struct clk_psc *psc = to_clk_psc(hw);
|
||||
unsigned long best = 0, now, maxdiv;
|
||||
int i;
|
||||
|
||||
maxdiv = psc->div[psc->num_div - 1];
|
||||
|
||||
for (i = 0; i < psc->num_div; i++) {
|
||||
if ((rate * psc->div[i]) == *parent_rate)
|
||||
return DIV_ROUND_UP_ULL((u64)*parent_rate, psc->div[i]);
|
||||
|
||||
now = DIV_ROUND_UP_ULL((u64)*parent_rate, psc->div[i]);
|
||||
|
||||
if (is_best(rate, now, best))
|
||||
best = now;
|
||||
}
|
||||
|
||||
if (!best)
|
||||
best = DIV_ROUND_UP_ULL(*parent_rate, maxdiv);
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
static int ep93xx_div_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_psc *psc = to_clk_psc(hw);
|
||||
u32 val = __raw_readl(psc->reg) & ~psc->mask;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < psc->num_div; i++)
|
||||
if (rate == parent_rate / psc->div[i]) {
|
||||
val |= i << psc->shift;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == psc->num_div)
|
||||
return -EINVAL;
|
||||
|
||||
ep93xx_syscon_swlocked_write(val, psc->reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops ep93xx_div_ops = {
|
||||
.enable = ep93xx_clk_enable,
|
||||
.disable = ep93xx_clk_disable,
|
||||
.is_enabled = ep93xx_clk_is_enabled,
|
||||
.recalc_rate = ep93xx_div_recalc_rate,
|
||||
.round_rate = ep93xx_div_round_rate,
|
||||
.set_rate = ep93xx_div_set_rate,
|
||||
};
|
||||
|
||||
static struct clk_hw *clk_hw_register_div(const char *name,
|
||||
const char *parent_name,
|
||||
void __iomem *reg,
|
||||
u8 enable_bit,
|
||||
u8 shift,
|
||||
u8 width,
|
||||
char *clk_divisors,
|
||||
u8 num_div)
|
||||
{
|
||||
struct clk_init_data init;
|
||||
struct clk_psc *psc;
|
||||
struct clk *clk;
|
||||
|
||||
psc = kzalloc(sizeof(*psc), GFP_KERNEL);
|
||||
if (!psc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &ep93xx_div_ops;
|
||||
init.flags = 0;
|
||||
init.parent_names = (parent_name ? &parent_name : NULL);
|
||||
init.num_parents = 1;
|
||||
|
||||
psc->reg = reg;
|
||||
psc->bit_idx = enable_bit;
|
||||
psc->mask = GENMASK(shift + width - 1, shift);
|
||||
psc->shift = shift;
|
||||
psc->div = clk_divisors;
|
||||
psc->num_div = num_div;
|
||||
psc->lock = &clk_lock;
|
||||
psc->hw.init = &init;
|
||||
|
||||
clk = clk_register(NULL, &psc->hw);
|
||||
if (IS_ERR(clk)) {
|
||||
kfree(psc);
|
||||
return ERR_CAST(clk);
|
||||
}
|
||||
return &psc->hw;
|
||||
}
|
||||
|
||||
struct ep93xx_gate {
|
||||
unsigned int bit;
|
||||
const char *dev_id;
|
||||
const char *con_id;
|
||||
};
|
||||
|
||||
static struct ep93xx_gate ep93xx_uarts[] = {
|
||||
{EP93XX_SYSCON_DEVCFG_U1EN, "apb:uart1", NULL},
|
||||
{EP93XX_SYSCON_DEVCFG_U2EN, "apb:uart2", NULL},
|
||||
{EP93XX_SYSCON_DEVCFG_U3EN, "apb:uart3", NULL},
|
||||
};
|
||||
|
||||
static void __init ep93xx_uart_clock_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
struct clk_hw *hw;
|
||||
u32 value;
|
||||
unsigned int clk_uart_div;
|
||||
|
||||
value = __raw_readl(EP93XX_SYSCON_PWRCNT);
|
||||
if (value & EP93XX_SYSCON_PWRCNT_UARTBAUD)
|
||||
clk_uart_div = 1;
|
||||
else
|
||||
clk_uart_div = 2;
|
||||
|
||||
hw = clk_hw_register_fixed_factor(NULL, "uart", "xtali", 0, 1, clk_uart_div);
|
||||
|
||||
/* parenting uart gate clocks to uart clock */
|
||||
for (i = 0; i < ARRAY_SIZE(ep93xx_uarts); i++) {
|
||||
hw = ep93xx_clk_register_gate(ep93xx_uarts[i].dev_id,
|
||||
"uart",
|
||||
EP93XX_SYSCON_DEVCFG,
|
||||
ep93xx_uarts[i].bit);
|
||||
|
||||
clk_hw_register_clkdev(hw, NULL, ep93xx_uarts[i].dev_id);
|
||||
}
|
||||
}
|
||||
|
||||
static struct ep93xx_gate ep93xx_dmas[] = {
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2P0, NULL, "m2p0"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2P1, NULL, "m2p1"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2P2, NULL, "m2p2"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2P3, NULL, "m2p3"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2P4, NULL, "m2p4"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2P5, NULL, "m2p5"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2P6, NULL, "m2p6"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2P7, NULL, "m2p7"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2P8, NULL, "m2p8"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2P9, NULL, "m2p9"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2M0, NULL, "m2m0"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2M1, NULL, "m2m1"},
|
||||
};
|
||||
|
||||
static void __init ep93xx_dma_clock_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
struct clk_hw *hw;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ep93xx_dmas); i++) {
|
||||
hw = clk_hw_register_gate(NULL, ep93xx_dmas[i].con_id,
|
||||
"hclk", 0,
|
||||
EP93XX_SYSCON_PWRCNT,
|
||||
ep93xx_dmas[i].bit,
|
||||
0,
|
||||
&clk_lock);
|
||||
|
||||
ret = clk_hw_register_clkdev(hw, ep93xx_dmas[i].con_id, NULL);
|
||||
if (ret)
|
||||
pr_err("%s: failed to register lookup %s\n",
|
||||
__func__, ep93xx_dmas[i].con_id);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init ep93xx_clock_init(void)
|
||||
{
|
||||
u32 value;
|
||||
struct clk_hw *hw;
|
||||
unsigned long clk_pll1_rate;
|
||||
unsigned long clk_f_rate;
|
||||
unsigned long clk_h_rate;
|
||||
unsigned long clk_p_rate;
|
||||
unsigned long clk_pll2_rate;
|
||||
unsigned int clk_f_div;
|
||||
unsigned int clk_h_div;
|
||||
unsigned int clk_p_div;
|
||||
unsigned int clk_usb_div;
|
||||
unsigned long clk_spi_div;
|
||||
|
||||
hw = clk_hw_register_fixed_rate(NULL, "xtali", NULL, 0, EP93XX_EXT_CLK_RATE);
|
||||
clk_hw_register_clkdev(hw, NULL, "xtali");
|
||||
|
||||
/* Determine the bootloader configured pll1 rate */
|
||||
value = __raw_readl(EP93XX_SYSCON_CLKSET1);
|
||||
if (!(value & EP93XX_SYSCON_CLKSET1_NBYP1))
|
||||
clk_pll1_rate = EP93XX_EXT_CLK_RATE;
|
||||
else
|
||||
clk_pll1_rate = calc_pll_rate(EP93XX_EXT_CLK_RATE, value);
|
||||
|
||||
hw = clk_hw_register_fixed_rate(NULL, "pll1", "xtali", 0, clk_pll1_rate);
|
||||
clk_hw_register_clkdev(hw, NULL, "pll1");
|
||||
|
||||
/* Initialize the pll1 derived clocks */
|
||||
clk_f_div = fclk_divisors[(value >> 25) & 0x7];
|
||||
clk_h_div = hclk_divisors[(value >> 20) & 0x7];
|
||||
clk_p_div = pclk_divisors[(value >> 18) & 0x3];
|
||||
|
||||
hw = clk_hw_register_fixed_factor(NULL, "fclk", "pll1", 0, 1, clk_f_div);
|
||||
clk_f_rate = clk_get_rate(hw->clk);
|
||||
hw = clk_hw_register_fixed_factor(NULL, "hclk", "pll1", 0, 1, clk_h_div);
|
||||
clk_h_rate = clk_get_rate(hw->clk);
|
||||
hw = clk_hw_register_fixed_factor(NULL, "pclk", "hclk", 0, 1, clk_p_div);
|
||||
clk_p_rate = clk_get_rate(hw->clk);
|
||||
|
||||
clk_hw_register_clkdev(hw, "apb_pclk", NULL);
|
||||
|
||||
ep93xx_dma_clock_init();
|
||||
|
||||
/* Determine the bootloader configured pll2 rate */
|
||||
value = __raw_readl(EP93XX_SYSCON_CLKSET2);
|
||||
if (!(value & EP93XX_SYSCON_CLKSET2_NBYP2))
|
||||
clk_pll2_rate = EP93XX_EXT_CLK_RATE;
|
||||
else if (value & EP93XX_SYSCON_CLKSET2_PLL2_EN)
|
||||
clk_pll2_rate = calc_pll_rate(EP93XX_EXT_CLK_RATE, value);
|
||||
else
|
||||
clk_pll2_rate = 0;
|
||||
|
||||
hw = clk_hw_register_fixed_rate(NULL, "pll2", "xtali", 0, clk_pll2_rate);
|
||||
clk_hw_register_clkdev(hw, NULL, "pll2");
|
||||
|
||||
/* Initialize the pll2 derived clocks */
|
||||
/*
|
||||
* These four bits set the divide ratio between the PLL2
|
||||
* output and the USB clock.
|
||||
* 0000 - Divide by 1
|
||||
* 0001 - Divide by 2
|
||||
* 0010 - Divide by 3
|
||||
* 0011 - Divide by 4
|
||||
* 0100 - Divide by 5
|
||||
* 0101 - Divide by 6
|
||||
* 0110 - Divide by 7
|
||||
* 0111 - Divide by 8
|
||||
* 1000 - Divide by 9
|
||||
* 1001 - Divide by 10
|
||||
* 1010 - Divide by 11
|
||||
* 1011 - Divide by 12
|
||||
* 1100 - Divide by 13
|
||||
* 1101 - Divide by 14
|
||||
* 1110 - Divide by 15
|
||||
* 1111 - Divide by 1
|
||||
* On power-on-reset these bits are reset to 0000b.
|
||||
*/
|
||||
clk_usb_div = (((value >> 28) & 0xf) + 1);
|
||||
hw = clk_hw_register_fixed_factor(NULL, "usb_clk", "pll2", 0, 1, clk_usb_div);
|
||||
hw = clk_hw_register_gate(NULL, "ohci-platform",
|
||||
"usb_clk", 0,
|
||||
EP93XX_SYSCON_PWRCNT,
|
||||
EP93XX_SYSCON_PWRCNT_USH_EN,
|
||||
0,
|
||||
&clk_lock);
|
||||
clk_hw_register_clkdev(hw, NULL, "ohci-platform");
|
||||
|
||||
/*
|
||||
* EP93xx SSP clock rate was doubled in version E2. For more information
|
||||
* see:
|
||||
* http://www.cirrus.com/en/pubs/appNote/AN273REV4.pdf
|
||||
*/
|
||||
clk_spi_div = 1;
|
||||
if (ep93xx_chip_revision() < EP93XX_CHIP_REV_E2)
|
||||
clk_spi_div = 2;
|
||||
hw = clk_hw_register_fixed_factor(NULL, "ep93xx-spi.0", "xtali", 0, 1, clk_spi_div);
|
||||
clk_hw_register_clkdev(hw, NULL, "ep93xx-spi.0");
|
||||
|
||||
/* pwm clock */
|
||||
hw = clk_hw_register_fixed_factor(NULL, "pwm_clk", "xtali", 0, 1, 1);
|
||||
clk_hw_register_clkdev(hw, "pwm_clk", NULL);
|
||||
|
||||
pr_info("PLL1 running at %ld MHz, PLL2 at %ld MHz\n",
|
||||
clk_pll1_rate / 1000000, clk_pll2_rate / 1000000);
|
||||
pr_info("FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",
|
||||
clk_f_rate / 1000000, clk_h_rate / 1000000,
|
||||
clk_p_rate / 1000000);
|
||||
|
||||
ep93xx_uart_clock_init();
|
||||
|
||||
/* touchscreen/adc clock */
|
||||
hw = clk_hw_register_div("ep93xx-adc",
|
||||
"xtali",
|
||||
EP93XX_SYSCON_KEYTCHCLKDIV,
|
||||
EP93XX_SYSCON_KEYTCHCLKDIV_TSEN,
|
||||
EP93XX_SYSCON_KEYTCHCLKDIV_ADIV,
|
||||
1,
|
||||
adc_divisors,
|
||||
ARRAY_SIZE(adc_divisors));
|
||||
|
||||
clk_hw_register_clkdev(hw, NULL, "ep93xx-adc");
|
||||
|
||||
/* keypad clock */
|
||||
hw = clk_hw_register_div("ep93xx-keypad",
|
||||
"xtali",
|
||||
EP93XX_SYSCON_KEYTCHCLKDIV,
|
||||
EP93XX_SYSCON_KEYTCHCLKDIV_KEN,
|
||||
EP93XX_SYSCON_KEYTCHCLKDIV_KDIV,
|
||||
1,
|
||||
adc_divisors,
|
||||
ARRAY_SIZE(adc_divisors));
|
||||
|
||||
clk_hw_register_clkdev(hw, NULL, "ep93xx-keypad");
|
||||
|
||||
/* On reset PDIV and VDIV is set to zero, while PDIV zero
|
||||
* means clock disable, VDIV shouldn't be zero.
|
||||
* So i set both dividers to minimum.
|
||||
*/
|
||||
/* ENA - Enable CLK divider. */
|
||||
/* PDIV - 00 - Disable clock */
|
||||
/* VDIV - at least 2 */
|
||||
/* Check and enable video clk registers */
|
||||
value = __raw_readl(EP93XX_SYSCON_VIDCLKDIV);
|
||||
value |= (1 << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | 2;
|
||||
ep93xx_syscon_swlocked_write(value, EP93XX_SYSCON_VIDCLKDIV);
|
||||
|
||||
/* check and enable i2s clk registers */
|
||||
value = __raw_readl(EP93XX_SYSCON_I2SCLKDIV);
|
||||
value |= (1 << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | 2;
|
||||
ep93xx_syscon_swlocked_write(value, EP93XX_SYSCON_I2SCLKDIV);
|
||||
|
||||
/* video clk */
|
||||
hw = clk_hw_register_ddiv("ep93xx-fb",
|
||||
EP93XX_SYSCON_VIDCLKDIV,
|
||||
EP93XX_SYSCON_CLKDIV_ENABLE);
|
||||
|
||||
clk_hw_register_clkdev(hw, NULL, "ep93xx-fb");
|
||||
|
||||
/* i2s clk */
|
||||
hw = clk_hw_register_ddiv("mclk",
|
||||
EP93XX_SYSCON_I2SCLKDIV,
|
||||
EP93XX_SYSCON_CLKDIV_ENABLE);
|
||||
|
||||
clk_hw_register_clkdev(hw, "mclk", "ep93xx-i2s");
|
||||
|
||||
/* i2s sclk */
|
||||
#define EP93XX_I2SCLKDIV_SDIV_SHIFT 16
|
||||
#define EP93XX_I2SCLKDIV_SDIV_WIDTH 1
|
||||
hw = clk_hw_register_div("sclk",
|
||||
"mclk",
|
||||
EP93XX_SYSCON_I2SCLKDIV,
|
||||
EP93XX_SYSCON_I2SCLKDIV_SENA,
|
||||
EP93XX_I2SCLKDIV_SDIV_SHIFT,
|
||||
EP93XX_I2SCLKDIV_SDIV_WIDTH,
|
||||
sclk_divisors,
|
||||
ARRAY_SIZE(sclk_divisors));
|
||||
|
||||
clk_hw_register_clkdev(hw, "sclk", "ep93xx-i2s");
|
||||
|
||||
/* i2s lrclk */
|
||||
#define EP93XX_I2SCLKDIV_LRDIV32_SHIFT 17
|
||||
#define EP93XX_I2SCLKDIV_LRDIV32_WIDTH 3
|
||||
hw = clk_hw_register_div("lrclk",
|
||||
"sclk",
|
||||
EP93XX_SYSCON_I2SCLKDIV,
|
||||
EP93XX_SYSCON_I2SCLKDIV_SENA,
|
||||
EP93XX_I2SCLKDIV_LRDIV32_SHIFT,
|
||||
EP93XX_I2SCLKDIV_LRDIV32_WIDTH,
|
||||
lrclk_divisors,
|
||||
ARRAY_SIZE(lrclk_divisors));
|
||||
|
||||
clk_hw_register_clkdev(hw, "lrclk", "ep93xx-i2s");
|
||||
|
||||
return 0;
|
||||
}
|
||||
postcore_initcall(ep93xx_clock_init);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,114 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* arch/arm/mach-ep93xx/dma.c
|
||||
*
|
||||
* Platform support code for the EP93xx dmaengine driver.
|
||||
*
|
||||
* Copyright (C) 2011 Mika Westerberg
|
||||
*
|
||||
* This work is based on the original dma-m2p implementation with
|
||||
* following copyrights:
|
||||
*
|
||||
* Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
|
||||
* Copyright (C) 2006 Applied Data Systems
|
||||
* Copyright (C) 2009 Ryan Mallon <rmallon@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <linux/platform_data/dma-ep93xx.h>
|
||||
#include "hardware.h"
|
||||
|
||||
#include "soc.h"
|
||||
|
||||
#define DMA_CHANNEL(_name, _base, _irq) \
|
||||
{ .name = (_name), .base = (_base), .irq = (_irq) }
|
||||
|
||||
/*
|
||||
* DMA M2P channels.
|
||||
*
|
||||
* On the EP93xx chip the following peripherals my be allocated to the 10
|
||||
* Memory to Internal Peripheral (M2P) channels (5 transmit + 5 receive).
|
||||
*
|
||||
* I2S contains 3 Tx and 3 Rx DMA Channels
|
||||
* AAC contains 3 Tx and 3 Rx DMA Channels
|
||||
* UART1 contains 1 Tx and 1 Rx DMA Channels
|
||||
* UART2 contains 1 Tx and 1 Rx DMA Channels
|
||||
* UART3 contains 1 Tx and 1 Rx DMA Channels
|
||||
* IrDA contains 1 Tx and 1 Rx DMA Channels
|
||||
*
|
||||
* Registers are mapped statically in ep93xx_map_io().
|
||||
*/
|
||||
static struct ep93xx_dma_chan_data ep93xx_dma_m2p_channels[] = {
|
||||
DMA_CHANNEL("m2p0", EP93XX_DMA_BASE + 0x0000, IRQ_EP93XX_DMAM2P0),
|
||||
DMA_CHANNEL("m2p1", EP93XX_DMA_BASE + 0x0040, IRQ_EP93XX_DMAM2P1),
|
||||
DMA_CHANNEL("m2p2", EP93XX_DMA_BASE + 0x0080, IRQ_EP93XX_DMAM2P2),
|
||||
DMA_CHANNEL("m2p3", EP93XX_DMA_BASE + 0x00c0, IRQ_EP93XX_DMAM2P3),
|
||||
DMA_CHANNEL("m2p4", EP93XX_DMA_BASE + 0x0240, IRQ_EP93XX_DMAM2P4),
|
||||
DMA_CHANNEL("m2p5", EP93XX_DMA_BASE + 0x0200, IRQ_EP93XX_DMAM2P5),
|
||||
DMA_CHANNEL("m2p6", EP93XX_DMA_BASE + 0x02c0, IRQ_EP93XX_DMAM2P6),
|
||||
DMA_CHANNEL("m2p7", EP93XX_DMA_BASE + 0x0280, IRQ_EP93XX_DMAM2P7),
|
||||
DMA_CHANNEL("m2p8", EP93XX_DMA_BASE + 0x0340, IRQ_EP93XX_DMAM2P8),
|
||||
DMA_CHANNEL("m2p9", EP93XX_DMA_BASE + 0x0300, IRQ_EP93XX_DMAM2P9),
|
||||
};
|
||||
|
||||
static struct ep93xx_dma_platform_data ep93xx_dma_m2p_data = {
|
||||
.channels = ep93xx_dma_m2p_channels,
|
||||
.num_channels = ARRAY_SIZE(ep93xx_dma_m2p_channels),
|
||||
};
|
||||
|
||||
static u64 ep93xx_dma_m2p_mask = DMA_BIT_MASK(32);
|
||||
|
||||
static struct platform_device ep93xx_dma_m2p_device = {
|
||||
.name = "ep93xx-dma-m2p",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &ep93xx_dma_m2p_data,
|
||||
.dma_mask = &ep93xx_dma_m2p_mask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* DMA M2M channels.
|
||||
*
|
||||
* There are 2 M2M channels which support memcpy/memset and in addition simple
|
||||
* hardware requests from/to SSP and IDE. We do not implement an external
|
||||
* hardware requests.
|
||||
*
|
||||
* Registers are mapped statically in ep93xx_map_io().
|
||||
*/
|
||||
static struct ep93xx_dma_chan_data ep93xx_dma_m2m_channels[] = {
|
||||
DMA_CHANNEL("m2m0", EP93XX_DMA_BASE + 0x0100, IRQ_EP93XX_DMAM2M0),
|
||||
DMA_CHANNEL("m2m1", EP93XX_DMA_BASE + 0x0140, IRQ_EP93XX_DMAM2M1),
|
||||
};
|
||||
|
||||
static struct ep93xx_dma_platform_data ep93xx_dma_m2m_data = {
|
||||
.channels = ep93xx_dma_m2m_channels,
|
||||
.num_channels = ARRAY_SIZE(ep93xx_dma_m2m_channels),
|
||||
};
|
||||
|
||||
static u64 ep93xx_dma_m2m_mask = DMA_BIT_MASK(32);
|
||||
|
||||
static struct platform_device ep93xx_dma_m2m_device = {
|
||||
.name = "ep93xx-dma-m2m",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &ep93xx_dma_m2m_data,
|
||||
.dma_mask = &ep93xx_dma_m2m_mask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
},
|
||||
};
|
||||
|
||||
static int __init ep93xx_dma_init(void)
|
||||
{
|
||||
platform_device_register(&ep93xx_dma_m2p_device);
|
||||
platform_device_register(&ep93xx_dma_m2m_device);
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(ep93xx_dma_init);
|
||||
@@ -1,368 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* arch/arm/mach-ep93xx/edb93xx.c
|
||||
* Cirrus Logic EDB93xx Development Board support.
|
||||
*
|
||||
* EDB93XX, EDB9301, EDB9307A
|
||||
* Copyright (C) 2008-2009 H Hartley Sweeten <hsweeten@visionengravers.com>
|
||||
*
|
||||
* EDB9302
|
||||
* Copyright (C) 2006 George Kashperko <george@chas.com.ua>
|
||||
*
|
||||
* EDB9302A, EDB9315, EDB9315A
|
||||
* Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
|
||||
*
|
||||
* EDB9307
|
||||
* Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
|
||||
*
|
||||
* EDB9312
|
||||
* Copyright (C) 2006 Infosys Technologies Limited
|
||||
* Toufeeq Hussain <toufeeq_hussain@infosys.com>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/gpio/machine.h>
|
||||
|
||||
#include <sound/cs4271.h>
|
||||
|
||||
#include "hardware.h"
|
||||
#include <linux/platform_data/video-ep93xx.h>
|
||||
#include <linux/platform_data/spi-ep93xx.h>
|
||||
#include "gpio-ep93xx.h"
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
#include "soc.h"
|
||||
|
||||
static void __init edb93xx_register_flash(void)
|
||||
{
|
||||
if (machine_is_edb9307() || machine_is_edb9312() ||
|
||||
machine_is_edb9315()) {
|
||||
ep93xx_register_flash(4, EP93XX_CS6_PHYS_BASE, SZ_32M);
|
||||
} else {
|
||||
ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_16M);
|
||||
}
|
||||
}
|
||||
|
||||
static struct ep93xx_eth_data __initdata edb93xx_eth_data = {
|
||||
.phy_id = 1,
|
||||
};
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* EDB93xx i2c peripheral handling
|
||||
*************************************************************************/
|
||||
|
||||
static struct i2c_board_info __initdata edb93xxa_i2c_board_info[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("isl1208", 0x6f),
|
||||
},
|
||||
};
|
||||
|
||||
static struct i2c_board_info __initdata edb93xx_i2c_board_info[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("ds1337", 0x68),
|
||||
},
|
||||
};
|
||||
|
||||
static void __init edb93xx_register_i2c(void)
|
||||
{
|
||||
if (machine_is_edb9302a() || machine_is_edb9307a() ||
|
||||
machine_is_edb9315a()) {
|
||||
ep93xx_register_i2c(edb93xxa_i2c_board_info,
|
||||
ARRAY_SIZE(edb93xxa_i2c_board_info));
|
||||
} else if (machine_is_edb9302() || machine_is_edb9307()
|
||||
|| machine_is_edb9312() || machine_is_edb9315()) {
|
||||
ep93xx_register_i2c(edb93xx_i2c_board_info,
|
||||
ARRAY_SIZE(edb93xx_i2c_board_info));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* EDB93xx SPI peripheral handling
|
||||
*************************************************************************/
|
||||
static struct cs4271_platform_data edb93xx_cs4271_data = {
|
||||
/* Intentionally left blank */
|
||||
};
|
||||
|
||||
static struct spi_board_info edb93xx_spi_board_info[] __initdata = {
|
||||
{
|
||||
.modalias = "cs4271",
|
||||
.platform_data = &edb93xx_cs4271_data,
|
||||
.max_speed_hz = 6000000,
|
||||
.bus_num = 0,
|
||||
.chip_select = 0,
|
||||
.mode = SPI_MODE_3,
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table edb93xx_spi_cs_gpio_table = {
|
||||
.dev_id = "spi0",
|
||||
.table = {
|
||||
GPIO_LOOKUP("A", 6, "cs", GPIO_ACTIVE_LOW),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
static struct ep93xx_spi_info edb93xx_spi_info __initdata = {
|
||||
/* Intentionally left blank */
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table edb93xx_cs4272_edb9301_gpio_table = {
|
||||
.dev_id = "spi0.0", /* CS0 on SPI0 */
|
||||
.table = {
|
||||
GPIO_LOOKUP("A", 1, "reset", GPIO_ACTIVE_LOW),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table edb93xx_cs4272_edb9302_gpio_table = {
|
||||
.dev_id = "spi0.0", /* CS0 on SPI0 */
|
||||
.table = {
|
||||
GPIO_LOOKUP("H", 2, "reset", GPIO_ACTIVE_LOW),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table edb93xx_cs4272_edb9315_gpio_table = {
|
||||
.dev_id = "spi0.0", /* CS0 on SPI0 */
|
||||
.table = {
|
||||
GPIO_LOOKUP("B", 6, "reset", GPIO_ACTIVE_LOW),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
static void __init edb93xx_register_spi(void)
|
||||
{
|
||||
if (machine_is_edb9301() || machine_is_edb9302())
|
||||
gpiod_add_lookup_table(&edb93xx_cs4272_edb9301_gpio_table);
|
||||
else if (machine_is_edb9302a() || machine_is_edb9307a())
|
||||
gpiod_add_lookup_table(&edb93xx_cs4272_edb9302_gpio_table);
|
||||
else if (machine_is_edb9315a())
|
||||
gpiod_add_lookup_table(&edb93xx_cs4272_edb9315_gpio_table);
|
||||
|
||||
gpiod_add_lookup_table(&edb93xx_spi_cs_gpio_table);
|
||||
ep93xx_register_spi(&edb93xx_spi_info, edb93xx_spi_board_info,
|
||||
ARRAY_SIZE(edb93xx_spi_board_info));
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* EDB93xx I2S
|
||||
*************************************************************************/
|
||||
static struct platform_device edb93xx_audio_device = {
|
||||
.name = "edb93xx-audio",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static int __init edb93xx_has_audio(void)
|
||||
{
|
||||
return (machine_is_edb9301() || machine_is_edb9302() ||
|
||||
machine_is_edb9302a() || machine_is_edb9307a() ||
|
||||
machine_is_edb9315a());
|
||||
}
|
||||
|
||||
static void __init edb93xx_register_i2s(void)
|
||||
{
|
||||
if (edb93xx_has_audio()) {
|
||||
ep93xx_register_i2s();
|
||||
platform_device_register(&edb93xx_audio_device);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* EDB93xx pwm
|
||||
*************************************************************************/
|
||||
static void __init edb93xx_register_pwm(void)
|
||||
{
|
||||
if (machine_is_edb9301() ||
|
||||
machine_is_edb9302() || machine_is_edb9302a()) {
|
||||
/* EP9301 and EP9302 only have pwm.1 (EGPIO14) */
|
||||
ep93xx_register_pwm(0, 1);
|
||||
} else if (machine_is_edb9307() || machine_is_edb9307a()) {
|
||||
/* EP9307 only has pwm.0 (PWMOUT) */
|
||||
ep93xx_register_pwm(1, 0);
|
||||
} else {
|
||||
/* EP9312 and EP9315 have both */
|
||||
ep93xx_register_pwm(1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* EDB93xx framebuffer
|
||||
*************************************************************************/
|
||||
static struct ep93xxfb_mach_info __initdata edb93xxfb_info = {
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
static int __init edb93xx_has_fb(void)
|
||||
{
|
||||
/* These platforms have an ep93xx with video capability */
|
||||
return machine_is_edb9307() || machine_is_edb9307a() ||
|
||||
machine_is_edb9312() || machine_is_edb9315() ||
|
||||
machine_is_edb9315a();
|
||||
}
|
||||
|
||||
static void __init edb93xx_register_fb(void)
|
||||
{
|
||||
if (!edb93xx_has_fb())
|
||||
return;
|
||||
|
||||
if (machine_is_edb9307a() || machine_is_edb9315a())
|
||||
edb93xxfb_info.flags |= EP93XXFB_USE_SDCSN0;
|
||||
else
|
||||
edb93xxfb_info.flags |= EP93XXFB_USE_SDCSN3;
|
||||
|
||||
ep93xx_register_fb(&edb93xxfb_info);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* EDB93xx IDE
|
||||
*************************************************************************/
|
||||
static int __init edb93xx_has_ide(void)
|
||||
{
|
||||
/*
|
||||
* Although EDB9312 and EDB9315 do have IDE capability, they have
|
||||
* INTRQ line wired as pull-up, which makes using IDE interface
|
||||
* problematic.
|
||||
*/
|
||||
return machine_is_edb9312() || machine_is_edb9315() ||
|
||||
machine_is_edb9315a();
|
||||
}
|
||||
|
||||
static void __init edb93xx_register_ide(void)
|
||||
{
|
||||
if (!edb93xx_has_ide())
|
||||
return;
|
||||
|
||||
ep93xx_register_ide();
|
||||
}
|
||||
|
||||
|
||||
static void __init edb93xx_init_machine(void)
|
||||
{
|
||||
ep93xx_init_devices();
|
||||
edb93xx_register_flash();
|
||||
ep93xx_register_eth(&edb93xx_eth_data, 1);
|
||||
edb93xx_register_i2c();
|
||||
edb93xx_register_spi();
|
||||
edb93xx_register_i2s();
|
||||
edb93xx_register_pwm();
|
||||
edb93xx_register_fb();
|
||||
edb93xx_register_ide();
|
||||
ep93xx_register_adc();
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_MACH_EDB9301
|
||||
MACHINE_START(EDB9301, "Cirrus Logic EDB9301 Evaluation Board")
|
||||
/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS,
|
||||
.map_io = ep93xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = edb93xx_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MACH_EDB9302
|
||||
MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board")
|
||||
/* Maintainer: George Kashperko <george@chas.com.ua> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS,
|
||||
.map_io = ep93xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = edb93xx_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MACH_EDB9302A
|
||||
MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board")
|
||||
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS,
|
||||
.map_io = ep93xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = edb93xx_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MACH_EDB9307
|
||||
MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board")
|
||||
/* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS,
|
||||
.map_io = ep93xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = edb93xx_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MACH_EDB9307A
|
||||
MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board")
|
||||
/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS,
|
||||
.map_io = ep93xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = edb93xx_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MACH_EDB9312
|
||||
MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
|
||||
/* Maintainer: Toufeeq Hussain <toufeeq_hussain@infosys.com> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS,
|
||||
.map_io = ep93xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = edb93xx_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MACH_EDB9315
|
||||
MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board")
|
||||
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS,
|
||||
.map_io = ep93xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = edb93xx_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MACH_EDB9315A
|
||||
MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board")
|
||||
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS,
|
||||
.map_io = ep93xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = edb93xx_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
||||
#endif
|
||||
@@ -1,38 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __ASM_ARCH_EP93XX_REGS_H
|
||||
#define __ASM_ARCH_EP93XX_REGS_H
|
||||
|
||||
/*
|
||||
* EP93xx linux memory map:
|
||||
*
|
||||
* virt phys size
|
||||
* fe800000 5M per-platform mappings
|
||||
* fed00000 80800000 2M APB
|
||||
* fef00000 80000000 1M AHB
|
||||
*/
|
||||
|
||||
#define EP93XX_AHB_PHYS_BASE 0x80000000
|
||||
#define EP93XX_AHB_VIRT_BASE 0xfef00000
|
||||
#define EP93XX_AHB_SIZE 0x00100000
|
||||
|
||||
#define EP93XX_AHB_PHYS(x) (EP93XX_AHB_PHYS_BASE + (x))
|
||||
#define EP93XX_AHB_IOMEM(x) IOMEM(EP93XX_AHB_VIRT_BASE + (x))
|
||||
|
||||
#define EP93XX_APB_PHYS_BASE 0x80800000
|
||||
#define EP93XX_APB_VIRT_BASE 0xfed00000
|
||||
#define EP93XX_APB_SIZE 0x00200000
|
||||
|
||||
#define EP93XX_APB_PHYS(x) (EP93XX_APB_PHYS_BASE + (x))
|
||||
#define EP93XX_APB_IOMEM(x) IOMEM(EP93XX_APB_VIRT_BASE + (x))
|
||||
|
||||
/* APB UARTs */
|
||||
#define EP93XX_UART1_PHYS_BASE EP93XX_APB_PHYS(0x000c0000)
|
||||
#define EP93XX_UART1_BASE EP93XX_APB_IOMEM(0x000c0000)
|
||||
|
||||
#define EP93XX_UART2_PHYS_BASE EP93XX_APB_PHYS(0x000d0000)
|
||||
#define EP93XX_UART2_BASE EP93XX_APB_IOMEM(0x000d0000)
|
||||
|
||||
#define EP93XX_UART3_PHYS_BASE EP93XX_APB_PHYS(0x000e0000)
|
||||
#define EP93XX_UART3_BASE EP93XX_APB_IOMEM(0x000e0000)
|
||||
|
||||
#endif
|
||||
@@ -1,111 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Include file for the EP93XX GPIO controller machine specifics */
|
||||
|
||||
#ifndef __GPIO_EP93XX_H
|
||||
#define __GPIO_EP93XX_H
|
||||
|
||||
#include "ep93xx-regs.h"
|
||||
|
||||
#define EP93XX_GPIO_PHYS_BASE EP93XX_APB_PHYS(0x00040000)
|
||||
#define EP93XX_GPIO_BASE EP93XX_APB_IOMEM(0x00040000)
|
||||
#define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x))
|
||||
#define EP93XX_GPIO_F_INT_STATUS EP93XX_GPIO_REG(0x5c)
|
||||
#define EP93XX_GPIO_A_INT_STATUS EP93XX_GPIO_REG(0xa0)
|
||||
#define EP93XX_GPIO_B_INT_STATUS EP93XX_GPIO_REG(0xbc)
|
||||
#define EP93XX_GPIO_EEDRIVE EP93XX_GPIO_REG(0xc8)
|
||||
|
||||
/* GPIO port A. */
|
||||
#define EP93XX_GPIO_LINE_A(x) ((x) + 0)
|
||||
#define EP93XX_GPIO_LINE_EGPIO0 EP93XX_GPIO_LINE_A(0)
|
||||
#define EP93XX_GPIO_LINE_EGPIO1 EP93XX_GPIO_LINE_A(1)
|
||||
#define EP93XX_GPIO_LINE_EGPIO2 EP93XX_GPIO_LINE_A(2)
|
||||
#define EP93XX_GPIO_LINE_EGPIO3 EP93XX_GPIO_LINE_A(3)
|
||||
#define EP93XX_GPIO_LINE_EGPIO4 EP93XX_GPIO_LINE_A(4)
|
||||
#define EP93XX_GPIO_LINE_EGPIO5 EP93XX_GPIO_LINE_A(5)
|
||||
#define EP93XX_GPIO_LINE_EGPIO6 EP93XX_GPIO_LINE_A(6)
|
||||
#define EP93XX_GPIO_LINE_EGPIO7 EP93XX_GPIO_LINE_A(7)
|
||||
|
||||
/* GPIO port B. */
|
||||
#define EP93XX_GPIO_LINE_B(x) ((x) + 8)
|
||||
#define EP93XX_GPIO_LINE_EGPIO8 EP93XX_GPIO_LINE_B(0)
|
||||
#define EP93XX_GPIO_LINE_EGPIO9 EP93XX_GPIO_LINE_B(1)
|
||||
#define EP93XX_GPIO_LINE_EGPIO10 EP93XX_GPIO_LINE_B(2)
|
||||
#define EP93XX_GPIO_LINE_EGPIO11 EP93XX_GPIO_LINE_B(3)
|
||||
#define EP93XX_GPIO_LINE_EGPIO12 EP93XX_GPIO_LINE_B(4)
|
||||
#define EP93XX_GPIO_LINE_EGPIO13 EP93XX_GPIO_LINE_B(5)
|
||||
#define EP93XX_GPIO_LINE_EGPIO14 EP93XX_GPIO_LINE_B(6)
|
||||
#define EP93XX_GPIO_LINE_EGPIO15 EP93XX_GPIO_LINE_B(7)
|
||||
|
||||
/* GPIO port C. */
|
||||
#define EP93XX_GPIO_LINE_C(x) ((x) + 40)
|
||||
#define EP93XX_GPIO_LINE_ROW0 EP93XX_GPIO_LINE_C(0)
|
||||
#define EP93XX_GPIO_LINE_ROW1 EP93XX_GPIO_LINE_C(1)
|
||||
#define EP93XX_GPIO_LINE_ROW2 EP93XX_GPIO_LINE_C(2)
|
||||
#define EP93XX_GPIO_LINE_ROW3 EP93XX_GPIO_LINE_C(3)
|
||||
#define EP93XX_GPIO_LINE_ROW4 EP93XX_GPIO_LINE_C(4)
|
||||
#define EP93XX_GPIO_LINE_ROW5 EP93XX_GPIO_LINE_C(5)
|
||||
#define EP93XX_GPIO_LINE_ROW6 EP93XX_GPIO_LINE_C(6)
|
||||
#define EP93XX_GPIO_LINE_ROW7 EP93XX_GPIO_LINE_C(7)
|
||||
|
||||
/* GPIO port D. */
|
||||
#define EP93XX_GPIO_LINE_D(x) ((x) + 24)
|
||||
#define EP93XX_GPIO_LINE_COL0 EP93XX_GPIO_LINE_D(0)
|
||||
#define EP93XX_GPIO_LINE_COL1 EP93XX_GPIO_LINE_D(1)
|
||||
#define EP93XX_GPIO_LINE_COL2 EP93XX_GPIO_LINE_D(2)
|
||||
#define EP93XX_GPIO_LINE_COL3 EP93XX_GPIO_LINE_D(3)
|
||||
#define EP93XX_GPIO_LINE_COL4 EP93XX_GPIO_LINE_D(4)
|
||||
#define EP93XX_GPIO_LINE_COL5 EP93XX_GPIO_LINE_D(5)
|
||||
#define EP93XX_GPIO_LINE_COL6 EP93XX_GPIO_LINE_D(6)
|
||||
#define EP93XX_GPIO_LINE_COL7 EP93XX_GPIO_LINE_D(7)
|
||||
|
||||
/* GPIO port E. */
|
||||
#define EP93XX_GPIO_LINE_E(x) ((x) + 32)
|
||||
#define EP93XX_GPIO_LINE_GRLED EP93XX_GPIO_LINE_E(0)
|
||||
#define EP93XX_GPIO_LINE_RDLED EP93XX_GPIO_LINE_E(1)
|
||||
#define EP93XX_GPIO_LINE_DIORn EP93XX_GPIO_LINE_E(2)
|
||||
#define EP93XX_GPIO_LINE_IDECS1n EP93XX_GPIO_LINE_E(3)
|
||||
#define EP93XX_GPIO_LINE_IDECS2n EP93XX_GPIO_LINE_E(4)
|
||||
#define EP93XX_GPIO_LINE_IDEDA0 EP93XX_GPIO_LINE_E(5)
|
||||
#define EP93XX_GPIO_LINE_IDEDA1 EP93XX_GPIO_LINE_E(6)
|
||||
#define EP93XX_GPIO_LINE_IDEDA2 EP93XX_GPIO_LINE_E(7)
|
||||
|
||||
/* GPIO port F. */
|
||||
#define EP93XX_GPIO_LINE_F(x) ((x) + 16)
|
||||
#define EP93XX_GPIO_LINE_WP EP93XX_GPIO_LINE_F(0)
|
||||
#define EP93XX_GPIO_LINE_MCCD1 EP93XX_GPIO_LINE_F(1)
|
||||
#define EP93XX_GPIO_LINE_MCCD2 EP93XX_GPIO_LINE_F(2)
|
||||
#define EP93XX_GPIO_LINE_MCBVD1 EP93XX_GPIO_LINE_F(3)
|
||||
#define EP93XX_GPIO_LINE_MCBVD2 EP93XX_GPIO_LINE_F(4)
|
||||
#define EP93XX_GPIO_LINE_VS1 EP93XX_GPIO_LINE_F(5)
|
||||
#define EP93XX_GPIO_LINE_READY EP93XX_GPIO_LINE_F(6)
|
||||
#define EP93XX_GPIO_LINE_VS2 EP93XX_GPIO_LINE_F(7)
|
||||
|
||||
/* GPIO port G. */
|
||||
#define EP93XX_GPIO_LINE_G(x) ((x) + 48)
|
||||
#define EP93XX_GPIO_LINE_EECLK EP93XX_GPIO_LINE_G(0)
|
||||
#define EP93XX_GPIO_LINE_EEDAT EP93XX_GPIO_LINE_G(1)
|
||||
#define EP93XX_GPIO_LINE_SLA0 EP93XX_GPIO_LINE_G(2)
|
||||
#define EP93XX_GPIO_LINE_SLA1 EP93XX_GPIO_LINE_G(3)
|
||||
#define EP93XX_GPIO_LINE_DD12 EP93XX_GPIO_LINE_G(4)
|
||||
#define EP93XX_GPIO_LINE_DD13 EP93XX_GPIO_LINE_G(5)
|
||||
#define EP93XX_GPIO_LINE_DD14 EP93XX_GPIO_LINE_G(6)
|
||||
#define EP93XX_GPIO_LINE_DD15 EP93XX_GPIO_LINE_G(7)
|
||||
|
||||
/* GPIO port H. */
|
||||
#define EP93XX_GPIO_LINE_H(x) ((x) + 56)
|
||||
#define EP93XX_GPIO_LINE_DD0 EP93XX_GPIO_LINE_H(0)
|
||||
#define EP93XX_GPIO_LINE_DD1 EP93XX_GPIO_LINE_H(1)
|
||||
#define EP93XX_GPIO_LINE_DD2 EP93XX_GPIO_LINE_H(2)
|
||||
#define EP93XX_GPIO_LINE_DD3 EP93XX_GPIO_LINE_H(3)
|
||||
#define EP93XX_GPIO_LINE_DD4 EP93XX_GPIO_LINE_H(4)
|
||||
#define EP93XX_GPIO_LINE_DD5 EP93XX_GPIO_LINE_H(5)
|
||||
#define EP93XX_GPIO_LINE_DD6 EP93XX_GPIO_LINE_H(6)
|
||||
#define EP93XX_GPIO_LINE_DD7 EP93XX_GPIO_LINE_H(7)
|
||||
|
||||
/* maximum value for gpio line identifiers */
|
||||
#define EP93XX_GPIO_LINE_MAX EP93XX_GPIO_LINE_H(7)
|
||||
|
||||
/* maximum value for irq capable line identifiers */
|
||||
#define EP93XX_GPIO_LINE_MAX_IRQ EP93XX_GPIO_LINE_F(7)
|
||||
|
||||
#endif /* __GPIO_EP93XX_H */
|
||||
@@ -1,25 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* arch/arm/mach-ep93xx/include/mach/hardware.h
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_HARDWARE_H
|
||||
#define __ASM_ARCH_HARDWARE_H
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
/*
|
||||
* The EP93xx has two external crystal oscillators. To generate the
|
||||
* required high-frequency clocks, the processor uses two phase-locked-
|
||||
* loops (PLLs) to multiply the incoming external clock signal to much
|
||||
* higher frequencies that are then divided down by programmable dividers
|
||||
* to produce the needed clocks. The PLLs operate independently of one
|
||||
* another.
|
||||
*/
|
||||
#define EP93XX_EXT_CLK_RATE 14745600
|
||||
#define EP93XX_EXT_RTC_RATE 32768
|
||||
|
||||
#define EP93XX_KEYTCHCLK_DIV4 (EP93XX_EXT_CLK_RATE / 4)
|
||||
#define EP93XX_KEYTCHCLK_DIV16 (EP93XX_EXT_CLK_RATE / 16)
|
||||
|
||||
#endif
|
||||
@@ -1,76 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __ASM_ARCH_IRQS_H
|
||||
#define __ASM_ARCH_IRQS_H
|
||||
|
||||
#define IRQ_EP93XX_VIC0 1
|
||||
|
||||
#define IRQ_EP93XX_COMMRX (IRQ_EP93XX_VIC0 + 2)
|
||||
#define IRQ_EP93XX_COMMTX (IRQ_EP93XX_VIC0 + 3)
|
||||
#define IRQ_EP93XX_TIMER1 (IRQ_EP93XX_VIC0 + 4)
|
||||
#define IRQ_EP93XX_TIMER2 (IRQ_EP93XX_VIC0 + 5)
|
||||
#define IRQ_EP93XX_AACINTR (IRQ_EP93XX_VIC0 + 6)
|
||||
#define IRQ_EP93XX_DMAM2P0 (IRQ_EP93XX_VIC0 + 7)
|
||||
#define IRQ_EP93XX_DMAM2P1 (IRQ_EP93XX_VIC0 + 8)
|
||||
#define IRQ_EP93XX_DMAM2P2 (IRQ_EP93XX_VIC0 + 9)
|
||||
#define IRQ_EP93XX_DMAM2P3 (IRQ_EP93XX_VIC0 + 10)
|
||||
#define IRQ_EP93XX_DMAM2P4 (IRQ_EP93XX_VIC0 + 11)
|
||||
#define IRQ_EP93XX_DMAM2P5 (IRQ_EP93XX_VIC0 + 12)
|
||||
#define IRQ_EP93XX_DMAM2P6 (IRQ_EP93XX_VIC0 + 13)
|
||||
#define IRQ_EP93XX_DMAM2P7 (IRQ_EP93XX_VIC0 + 14)
|
||||
#define IRQ_EP93XX_DMAM2P8 (IRQ_EP93XX_VIC0 + 15)
|
||||
#define IRQ_EP93XX_DMAM2P9 (IRQ_EP93XX_VIC0 + 16)
|
||||
#define IRQ_EP93XX_DMAM2M0 (IRQ_EP93XX_VIC0 + 17)
|
||||
#define IRQ_EP93XX_DMAM2M1 (IRQ_EP93XX_VIC0 + 18)
|
||||
#define IRQ_EP93XX_GPIO0MUX (IRQ_EP93XX_VIC0 + 19)
|
||||
#define IRQ_EP93XX_GPIO1MUX (IRQ_EP93XX_VIC0 + 20)
|
||||
#define IRQ_EP93XX_GPIO2MUX (IRQ_EP93XX_VIC0 + 21)
|
||||
#define IRQ_EP93XX_GPIO3MUX (IRQ_EP93XX_VIC0 + 22)
|
||||
#define IRQ_EP93XX_UART1RX (IRQ_EP93XX_VIC0 + 23)
|
||||
#define IRQ_EP93XX_UART1TX (IRQ_EP93XX_VIC0 + 24)
|
||||
#define IRQ_EP93XX_UART2RX (IRQ_EP93XX_VIC0 + 25)
|
||||
#define IRQ_EP93XX_UART2TX (IRQ_EP93XX_VIC0 + 26)
|
||||
#define IRQ_EP93XX_UART3RX (IRQ_EP93XX_VIC0 + 27)
|
||||
#define IRQ_EP93XX_UART3TX (IRQ_EP93XX_VIC0 + 28)
|
||||
#define IRQ_EP93XX_KEY (IRQ_EP93XX_VIC0 + 29)
|
||||
#define IRQ_EP93XX_TOUCH (IRQ_EP93XX_VIC0 + 30)
|
||||
#define EP93XX_VIC1_VALID_IRQ_MASK 0x7ffffffc
|
||||
|
||||
#define IRQ_EP93XX_VIC1 (IRQ_EP93XX_VIC0 + 32)
|
||||
|
||||
#define IRQ_EP93XX_EXT0 (IRQ_EP93XX_VIC1 + 0)
|
||||
#define IRQ_EP93XX_EXT1 (IRQ_EP93XX_VIC1 + 1)
|
||||
#define IRQ_EP93XX_EXT2 (IRQ_EP93XX_VIC1 + 2)
|
||||
#define IRQ_EP93XX_64HZ (IRQ_EP93XX_VIC1 + 3)
|
||||
#define IRQ_EP93XX_WATCHDOG (IRQ_EP93XX_VIC1 + 4)
|
||||
#define IRQ_EP93XX_RTC (IRQ_EP93XX_VIC1 + 5)
|
||||
#define IRQ_EP93XX_IRDA (IRQ_EP93XX_VIC1 + 6)
|
||||
#define IRQ_EP93XX_ETHERNET (IRQ_EP93XX_VIC1 + 7)
|
||||
#define IRQ_EP93XX_EXT3 (IRQ_EP93XX_VIC1 + 8)
|
||||
#define IRQ_EP93XX_PROG (IRQ_EP93XX_VIC1 + 9)
|
||||
#define IRQ_EP93XX_1HZ (IRQ_EP93XX_VIC1 + 10)
|
||||
#define IRQ_EP93XX_VSYNC (IRQ_EP93XX_VIC1 + 11)
|
||||
#define IRQ_EP93XX_VIDEO_FIFO (IRQ_EP93XX_VIC1 + 12)
|
||||
#define IRQ_EP93XX_SSP1RX (IRQ_EP93XX_VIC1 + 13)
|
||||
#define IRQ_EP93XX_SSP1TX (IRQ_EP93XX_VIC1 + 14)
|
||||
#define IRQ_EP93XX_GPIO4MUX (IRQ_EP93XX_VIC1 + 15)
|
||||
#define IRQ_EP93XX_GPIO5MUX (IRQ_EP93XX_VIC1 + 16)
|
||||
#define IRQ_EP93XX_GPIO6MUX (IRQ_EP93XX_VIC1 + 17)
|
||||
#define IRQ_EP93XX_GPIO7MUX (IRQ_EP93XX_VIC1 + 18)
|
||||
#define IRQ_EP93XX_TIMER3 (IRQ_EP93XX_VIC1 + 19)
|
||||
#define IRQ_EP93XX_UART1 (IRQ_EP93XX_VIC1 + 20)
|
||||
#define IRQ_EP93XX_SSP (IRQ_EP93XX_VIC1 + 21)
|
||||
#define IRQ_EP93XX_UART2 (IRQ_EP93XX_VIC1 + 22)
|
||||
#define IRQ_EP93XX_UART3 (IRQ_EP93XX_VIC1 + 23)
|
||||
#define IRQ_EP93XX_USB (IRQ_EP93XX_VIC1 + 24)
|
||||
#define IRQ_EP93XX_ETHERNET_PME (IRQ_EP93XX_VIC1 + 25)
|
||||
#define IRQ_EP93XX_DSP (IRQ_EP93XX_VIC1 + 26)
|
||||
#define IRQ_EP93XX_GPIO_AB (IRQ_EP93XX_VIC1 + 27)
|
||||
#define IRQ_EP93XX_SAI (IRQ_EP93XX_VIC1 + 28)
|
||||
#define EP93XX_VIC2_VALID_IRQ_MASK 0x1fffffff
|
||||
|
||||
#define NR_EP93XX_IRQS (IRQ_EP93XX_VIC1 + 32 + 24)
|
||||
|
||||
#define EP93XX_BOARD_IRQ(x) (NR_EP93XX_IRQS + (x))
|
||||
#define EP93XX_BOARD_IRQS 32
|
||||
|
||||
#endif
|
||||
@@ -1,42 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* arch/arm/mach-ep93xx/include/mach/platform.h
|
||||
*/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/platform_data/eth-ep93xx.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
struct device;
|
||||
struct i2c_board_info;
|
||||
struct spi_board_info;
|
||||
struct platform_device;
|
||||
struct ep93xxfb_mach_info;
|
||||
struct ep93xx_keypad_platform_data;
|
||||
struct ep93xx_spi_info;
|
||||
|
||||
void ep93xx_map_io(void);
|
||||
void ep93xx_init_irq(void);
|
||||
|
||||
void ep93xx_register_flash(unsigned int width,
|
||||
resource_size_t start, resource_size_t size);
|
||||
|
||||
void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr);
|
||||
void ep93xx_register_i2c(struct i2c_board_info *devices, int num);
|
||||
void ep93xx_register_spi(struct ep93xx_spi_info *info,
|
||||
struct spi_board_info *devices, int num);
|
||||
void ep93xx_register_fb(struct ep93xxfb_mach_info *data);
|
||||
void ep93xx_register_pwm(int pwm0, int pwm1);
|
||||
void ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data);
|
||||
void ep93xx_register_i2s(void);
|
||||
void ep93xx_register_ac97(void);
|
||||
void ep93xx_register_ide(void);
|
||||
void ep93xx_register_adc(void);
|
||||
|
||||
struct device *ep93xx_init_devices(void);
|
||||
extern void ep93xx_timer_init(void);
|
||||
|
||||
void ep93xx_restart(enum reboot_mode, const char *);
|
||||
|
||||
#endif
|
||||
@@ -1,212 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* arch/arm/mach-ep93xx/soc.h
|
||||
*
|
||||
* Copyright (C) 2012 Open Kernel Labs <www.ok-labs.com>
|
||||
* Copyright (C) 2012 Ryan Mallon <rmallon@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _EP93XX_SOC_H
|
||||
#define _EP93XX_SOC_H
|
||||
|
||||
#include "ep93xx-regs.h"
|
||||
#include "irqs.h"
|
||||
|
||||
/*
|
||||
* EP93xx Physical Memory Map:
|
||||
*
|
||||
* The ASDO pin is sampled at system reset to select a synchronous or
|
||||
* asynchronous boot configuration. When ASDO is "1" (i.e. pulled-up)
|
||||
* the synchronous boot mode is selected. When ASDO is "0" (i.e
|
||||
* pulled-down) the asynchronous boot mode is selected.
|
||||
*
|
||||
* In synchronous boot mode nSDCE3 is decoded starting at physical address
|
||||
* 0x00000000 and nCS0 is decoded starting at 0xf0000000. For asynchronous
|
||||
* boot mode they are swapped with nCS0 decoded at 0x00000000 ann nSDCE3
|
||||
* decoded at 0xf0000000.
|
||||
*
|
||||
* There is known errata for the EP93xx dealing with External Memory
|
||||
* Configurations. Please refer to "AN273: EP93xx Silicon Rev E Design
|
||||
* Guidelines" for more information. This document can be found at:
|
||||
*
|
||||
* http://www.cirrus.com/en/pubs/appNote/AN273REV4.pdf
|
||||
*/
|
||||
|
||||
#define EP93XX_CS0_PHYS_BASE_ASYNC 0x00000000 /* ASDO Pin = 0 */
|
||||
#define EP93XX_SDCE3_PHYS_BASE_SYNC 0x00000000 /* ASDO Pin = 1 */
|
||||
#define EP93XX_CS1_PHYS_BASE 0x10000000
|
||||
#define EP93XX_CS2_PHYS_BASE 0x20000000
|
||||
#define EP93XX_CS3_PHYS_BASE 0x30000000
|
||||
#define EP93XX_PCMCIA_PHYS_BASE 0x40000000
|
||||
#define EP93XX_CS6_PHYS_BASE 0x60000000
|
||||
#define EP93XX_CS7_PHYS_BASE 0x70000000
|
||||
#define EP93XX_SDCE0_PHYS_BASE 0xc0000000
|
||||
#define EP93XX_SDCE1_PHYS_BASE 0xd0000000
|
||||
#define EP93XX_SDCE2_PHYS_BASE 0xe0000000
|
||||
#define EP93XX_SDCE3_PHYS_BASE_ASYNC 0xf0000000 /* ASDO Pin = 0 */
|
||||
#define EP93XX_CS0_PHYS_BASE_SYNC 0xf0000000 /* ASDO Pin = 1 */
|
||||
|
||||
/* AHB peripherals */
|
||||
#define EP93XX_DMA_BASE EP93XX_AHB_IOMEM(0x00000000)
|
||||
|
||||
#define EP93XX_ETHERNET_PHYS_BASE EP93XX_AHB_PHYS(0x00010000)
|
||||
#define EP93XX_ETHERNET_BASE EP93XX_AHB_IOMEM(0x00010000)
|
||||
|
||||
#define EP93XX_USB_PHYS_BASE EP93XX_AHB_PHYS(0x00020000)
|
||||
#define EP93XX_USB_BASE EP93XX_AHB_IOMEM(0x00020000)
|
||||
|
||||
#define EP93XX_RASTER_PHYS_BASE EP93XX_AHB_PHYS(0x00030000)
|
||||
#define EP93XX_RASTER_BASE EP93XX_AHB_IOMEM(0x00030000)
|
||||
|
||||
#define EP93XX_GRAPHICS_ACCEL_BASE EP93XX_AHB_IOMEM(0x00040000)
|
||||
|
||||
#define EP93XX_SDRAM_CONTROLLER_BASE EP93XX_AHB_IOMEM(0x00060000)
|
||||
|
||||
#define EP93XX_PCMCIA_CONTROLLER_BASE EP93XX_AHB_IOMEM(0x00080000)
|
||||
|
||||
#define EP93XX_BOOT_ROM_BASE EP93XX_AHB_IOMEM(0x00090000)
|
||||
|
||||
#define EP93XX_IDE_PHYS_BASE EP93XX_AHB_PHYS(0x000a0000)
|
||||
#define EP93XX_IDE_BASE EP93XX_AHB_IOMEM(0x000a0000)
|
||||
|
||||
#define EP93XX_VIC1_BASE EP93XX_AHB_IOMEM(0x000b0000)
|
||||
|
||||
#define EP93XX_VIC2_BASE EP93XX_AHB_IOMEM(0x000c0000)
|
||||
|
||||
/* APB peripherals */
|
||||
#define EP93XX_TIMER_BASE EP93XX_APB_IOMEM(0x00010000)
|
||||
|
||||
#define EP93XX_I2S_PHYS_BASE EP93XX_APB_PHYS(0x00020000)
|
||||
#define EP93XX_I2S_BASE EP93XX_APB_IOMEM(0x00020000)
|
||||
|
||||
#define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000)
|
||||
|
||||
#define EP93XX_AAC_PHYS_BASE EP93XX_APB_PHYS(0x00080000)
|
||||
#define EP93XX_AAC_BASE EP93XX_APB_IOMEM(0x00080000)
|
||||
|
||||
#define EP93XX_SPI_PHYS_BASE EP93XX_APB_PHYS(0x000a0000)
|
||||
#define EP93XX_SPI_BASE EP93XX_APB_IOMEM(0x000a0000)
|
||||
|
||||
#define EP93XX_IRDA_BASE EP93XX_APB_IOMEM(0x000b0000)
|
||||
|
||||
#define EP93XX_KEY_MATRIX_PHYS_BASE EP93XX_APB_PHYS(0x000f0000)
|
||||
#define EP93XX_KEY_MATRIX_BASE EP93XX_APB_IOMEM(0x000f0000)
|
||||
|
||||
#define EP93XX_ADC_PHYS_BASE EP93XX_APB_PHYS(0x00100000)
|
||||
#define EP93XX_ADC_BASE EP93XX_APB_IOMEM(0x00100000)
|
||||
#define EP93XX_TOUCHSCREEN_BASE EP93XX_APB_IOMEM(0x00100000)
|
||||
|
||||
#define EP93XX_PWM_PHYS_BASE EP93XX_APB_PHYS(0x00110000)
|
||||
#define EP93XX_PWM_BASE EP93XX_APB_IOMEM(0x00110000)
|
||||
|
||||
#define EP93XX_RTC_PHYS_BASE EP93XX_APB_PHYS(0x00120000)
|
||||
#define EP93XX_RTC_BASE EP93XX_APB_IOMEM(0x00120000)
|
||||
|
||||
#define EP93XX_WATCHDOG_PHYS_BASE EP93XX_APB_PHYS(0x00140000)
|
||||
#define EP93XX_WATCHDOG_BASE EP93XX_APB_IOMEM(0x00140000)
|
||||
|
||||
/* System controller */
|
||||
#define EP93XX_SYSCON_BASE EP93XX_APB_IOMEM(0x00130000)
|
||||
#define EP93XX_SYSCON_REG(x) (EP93XX_SYSCON_BASE + (x))
|
||||
#define EP93XX_SYSCON_POWER_STATE EP93XX_SYSCON_REG(0x00)
|
||||
#define EP93XX_SYSCON_PWRCNT EP93XX_SYSCON_REG(0x04)
|
||||
#define EP93XX_SYSCON_PWRCNT_FIR_EN (1<<31)
|
||||
#define EP93XX_SYSCON_PWRCNT_UARTBAUD (1<<29)
|
||||
#define EP93XX_SYSCON_PWRCNT_USH_EN 28
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2M1 27
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2M0 26
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P8 25
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P9 24
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P6 23
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P7 22
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P4 21
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P5 20
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P2 19
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P3 18
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P0 17
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P1 16
|
||||
#define EP93XX_SYSCON_HALT EP93XX_SYSCON_REG(0x08)
|
||||
#define EP93XX_SYSCON_STANDBY EP93XX_SYSCON_REG(0x0c)
|
||||
#define EP93XX_SYSCON_CLKSET1 EP93XX_SYSCON_REG(0x20)
|
||||
#define EP93XX_SYSCON_CLKSET1_NBYP1 (1<<23)
|
||||
#define EP93XX_SYSCON_CLKSET2 EP93XX_SYSCON_REG(0x24)
|
||||
#define EP93XX_SYSCON_CLKSET2_NBYP2 (1<<19)
|
||||
#define EP93XX_SYSCON_CLKSET2_PLL2_EN (1<<18)
|
||||
#define EP93XX_SYSCON_DEVCFG EP93XX_SYSCON_REG(0x80)
|
||||
#define EP93XX_SYSCON_DEVCFG_SWRST (1<<31)
|
||||
#define EP93XX_SYSCON_DEVCFG_D1ONG (1<<30)
|
||||
#define EP93XX_SYSCON_DEVCFG_D0ONG (1<<29)
|
||||
#define EP93XX_SYSCON_DEVCFG_IONU2 (1<<28)
|
||||
#define EP93XX_SYSCON_DEVCFG_GONK (1<<27)
|
||||
#define EP93XX_SYSCON_DEVCFG_TONG (1<<26)
|
||||
#define EP93XX_SYSCON_DEVCFG_MONG (1<<25)
|
||||
#define EP93XX_SYSCON_DEVCFG_U3EN 24
|
||||
#define EP93XX_SYSCON_DEVCFG_CPENA (1<<23)
|
||||
#define EP93XX_SYSCON_DEVCFG_A2ONG (1<<22)
|
||||
#define EP93XX_SYSCON_DEVCFG_A1ONG (1<<21)
|
||||
#define EP93XX_SYSCON_DEVCFG_U2EN 20
|
||||
#define EP93XX_SYSCON_DEVCFG_EXVC (1<<19)
|
||||
#define EP93XX_SYSCON_DEVCFG_U1EN 18
|
||||
#define EP93XX_SYSCON_DEVCFG_TIN (1<<17)
|
||||
#define EP93XX_SYSCON_DEVCFG_HC3IN (1<<15)
|
||||
#define EP93XX_SYSCON_DEVCFG_HC3EN (1<<14)
|
||||
#define EP93XX_SYSCON_DEVCFG_HC1IN (1<<13)
|
||||
#define EP93XX_SYSCON_DEVCFG_HC1EN (1<<12)
|
||||
#define EP93XX_SYSCON_DEVCFG_HONIDE (1<<11)
|
||||
#define EP93XX_SYSCON_DEVCFG_GONIDE (1<<10)
|
||||
#define EP93XX_SYSCON_DEVCFG_PONG (1<<9)
|
||||
#define EP93XX_SYSCON_DEVCFG_EONIDE (1<<8)
|
||||
#define EP93XX_SYSCON_DEVCFG_I2SONSSP (1<<7)
|
||||
#define EP93XX_SYSCON_DEVCFG_I2SONAC97 (1<<6)
|
||||
#define EP93XX_SYSCON_DEVCFG_RASONP3 (1<<4)
|
||||
#define EP93XX_SYSCON_DEVCFG_RAS (1<<3)
|
||||
#define EP93XX_SYSCON_DEVCFG_ADCPD (1<<2)
|
||||
#define EP93XX_SYSCON_DEVCFG_KEYS (1<<1)
|
||||
#define EP93XX_SYSCON_DEVCFG_SHENA (1<<0)
|
||||
#define EP93XX_SYSCON_VIDCLKDIV EP93XX_SYSCON_REG(0x84)
|
||||
#define EP93XX_SYSCON_CLKDIV_ENABLE 15
|
||||
#define EP93XX_SYSCON_CLKDIV_ESEL (1<<14)
|
||||
#define EP93XX_SYSCON_CLKDIV_PSEL (1<<13)
|
||||
#define EP93XX_SYSCON_CLKDIV_PDIV_SHIFT 8
|
||||
#define EP93XX_SYSCON_I2SCLKDIV EP93XX_SYSCON_REG(0x8c)
|
||||
#define EP93XX_SYSCON_I2SCLKDIV_SENA 31
|
||||
#define EP93XX_SYSCON_I2SCLKDIV_ORIDE (1<<29)
|
||||
#define EP93XX_SYSCON_I2SCLKDIV_SPOL (1<<19)
|
||||
#define EP93XX_I2SCLKDIV_SDIV (1 << 16)
|
||||
#define EP93XX_I2SCLKDIV_LRDIV32 (0 << 17)
|
||||
#define EP93XX_I2SCLKDIV_LRDIV64 (1 << 17)
|
||||
#define EP93XX_I2SCLKDIV_LRDIV128 (2 << 17)
|
||||
#define EP93XX_I2SCLKDIV_LRDIV_MASK (3 << 17)
|
||||
#define EP93XX_SYSCON_KEYTCHCLKDIV EP93XX_SYSCON_REG(0x90)
|
||||
#define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN 31
|
||||
#define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV 16
|
||||
#define EP93XX_SYSCON_KEYTCHCLKDIV_KEN 15
|
||||
#define EP93XX_SYSCON_KEYTCHCLKDIV_KDIV (1<<0)
|
||||
#define EP93XX_SYSCON_SYSCFG EP93XX_SYSCON_REG(0x9c)
|
||||
#define EP93XX_SYSCON_SYSCFG_REV_MASK (0xf0000000)
|
||||
#define EP93XX_SYSCON_SYSCFG_REV_SHIFT (28)
|
||||
#define EP93XX_SYSCON_SYSCFG_SBOOT (1<<8)
|
||||
#define EP93XX_SYSCON_SYSCFG_LCSN7 (1<<7)
|
||||
#define EP93XX_SYSCON_SYSCFG_LCSN6 (1<<6)
|
||||
#define EP93XX_SYSCON_SYSCFG_LASDO (1<<5)
|
||||
#define EP93XX_SYSCON_SYSCFG_LEEDA (1<<4)
|
||||
#define EP93XX_SYSCON_SYSCFG_LEECLK (1<<3)
|
||||
#define EP93XX_SYSCON_SYSCFG_LCSN2 (1<<1)
|
||||
#define EP93XX_SYSCON_SYSCFG_LCSN1 (1<<0)
|
||||
#define EP93XX_SYSCON_SWLOCK EP93XX_SYSCON_REG(0xc0)
|
||||
|
||||
/* EP93xx System Controller software locked register write */
|
||||
void ep93xx_syscon_swlocked_write(unsigned int val, void __iomem *reg);
|
||||
void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits);
|
||||
|
||||
static inline void ep93xx_devcfg_set_bits(unsigned int bits)
|
||||
{
|
||||
ep93xx_devcfg_set_clear(bits, 0x00);
|
||||
}
|
||||
|
||||
static inline void ep93xx_devcfg_clear_bits(unsigned int bits)
|
||||
{
|
||||
ep93xx_devcfg_set_clear(0x00, bits);
|
||||
}
|
||||
|
||||
#endif /* _EP93XX_SOC_H */
|
||||
@@ -1,143 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/sched_clock.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include "soc.h"
|
||||
#include "platform.h"
|
||||
|
||||
/*************************************************************************
|
||||
* Timer handling for EP93xx
|
||||
*************************************************************************
|
||||
* The ep93xx has four internal timers. Timers 1, 2 (both 16 bit) and
|
||||
* 3 (32 bit) count down at 508 kHz, are self-reloading, and can generate
|
||||
* an interrupt on underflow. Timer 4 (40 bit) counts down at 983.04 kHz,
|
||||
* is free-running, and can't generate interrupts.
|
||||
*
|
||||
* The 508 kHz timers are ideal for use for the timer interrupt, as the
|
||||
* most common values of HZ divide 508 kHz nicely. We pick the 32 bit
|
||||
* timer (timer 3) to get as long sleep intervals as possible when using
|
||||
* CONFIG_NO_HZ.
|
||||
*
|
||||
* The higher clock rate of timer 4 makes it a better choice than the
|
||||
* other timers for use as clock source and for sched_clock(), providing
|
||||
* a stable 40 bit time base.
|
||||
*************************************************************************
|
||||
*/
|
||||
#define EP93XX_TIMER_REG(x) (EP93XX_TIMER_BASE + (x))
|
||||
#define EP93XX_TIMER1_LOAD EP93XX_TIMER_REG(0x00)
|
||||
#define EP93XX_TIMER1_VALUE EP93XX_TIMER_REG(0x04)
|
||||
#define EP93XX_TIMER1_CONTROL EP93XX_TIMER_REG(0x08)
|
||||
#define EP93XX_TIMER123_CONTROL_ENABLE (1 << 7)
|
||||
#define EP93XX_TIMER123_CONTROL_MODE (1 << 6)
|
||||
#define EP93XX_TIMER123_CONTROL_CLKSEL (1 << 3)
|
||||
#define EP93XX_TIMER1_CLEAR EP93XX_TIMER_REG(0x0c)
|
||||
#define EP93XX_TIMER2_LOAD EP93XX_TIMER_REG(0x20)
|
||||
#define EP93XX_TIMER2_VALUE EP93XX_TIMER_REG(0x24)
|
||||
#define EP93XX_TIMER2_CONTROL EP93XX_TIMER_REG(0x28)
|
||||
#define EP93XX_TIMER2_CLEAR EP93XX_TIMER_REG(0x2c)
|
||||
#define EP93XX_TIMER4_VALUE_LOW EP93XX_TIMER_REG(0x60)
|
||||
#define EP93XX_TIMER4_VALUE_HIGH EP93XX_TIMER_REG(0x64)
|
||||
#define EP93XX_TIMER4_VALUE_HIGH_ENABLE (1 << 8)
|
||||
#define EP93XX_TIMER3_LOAD EP93XX_TIMER_REG(0x80)
|
||||
#define EP93XX_TIMER3_VALUE EP93XX_TIMER_REG(0x84)
|
||||
#define EP93XX_TIMER3_CONTROL EP93XX_TIMER_REG(0x88)
|
||||
#define EP93XX_TIMER3_CLEAR EP93XX_TIMER_REG(0x8c)
|
||||
|
||||
#define EP93XX_TIMER123_RATE 508469
|
||||
#define EP93XX_TIMER4_RATE 983040
|
||||
|
||||
static u64 notrace ep93xx_read_sched_clock(void)
|
||||
{
|
||||
u64 ret;
|
||||
|
||||
ret = readl(EP93XX_TIMER4_VALUE_LOW);
|
||||
ret |= ((u64) (readl(EP93XX_TIMER4_VALUE_HIGH) & 0xff) << 32);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u64 ep93xx_clocksource_read(struct clocksource *c)
|
||||
{
|
||||
u64 ret;
|
||||
|
||||
ret = readl(EP93XX_TIMER4_VALUE_LOW);
|
||||
ret |= ((u64) (readl(EP93XX_TIMER4_VALUE_HIGH) & 0xff) << 32);
|
||||
return (u64) ret;
|
||||
}
|
||||
|
||||
static int ep93xx_clkevt_set_next_event(unsigned long next,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
/* Default mode: periodic, off, 508 kHz */
|
||||
u32 tmode = EP93XX_TIMER123_CONTROL_MODE |
|
||||
EP93XX_TIMER123_CONTROL_CLKSEL;
|
||||
|
||||
/* Clear timer */
|
||||
writel(tmode, EP93XX_TIMER3_CONTROL);
|
||||
|
||||
/* Set next event */
|
||||
writel(next, EP93XX_TIMER3_LOAD);
|
||||
writel(tmode | EP93XX_TIMER123_CONTROL_ENABLE,
|
||||
EP93XX_TIMER3_CONTROL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ep93xx_clkevt_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
/* Disable timer */
|
||||
writel(0, EP93XX_TIMER3_CONTROL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clock_event_device ep93xx_clockevent = {
|
||||
.name = "timer1",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_state_shutdown = ep93xx_clkevt_shutdown,
|
||||
.set_state_oneshot = ep93xx_clkevt_shutdown,
|
||||
.tick_resume = ep93xx_clkevt_shutdown,
|
||||
.set_next_event = ep93xx_clkevt_set_next_event,
|
||||
.rating = 300,
|
||||
};
|
||||
|
||||
static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct clock_event_device *evt = dev_id;
|
||||
|
||||
/* Writing any value clears the timer interrupt */
|
||||
writel(1, EP93XX_TIMER3_CLEAR);
|
||||
|
||||
evt->event_handler(evt);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
void __init ep93xx_timer_init(void)
|
||||
{
|
||||
int irq = IRQ_EP93XX_TIMER3;
|
||||
unsigned long flags = IRQF_TIMER | IRQF_IRQPOLL;
|
||||
|
||||
/* Enable and register clocksource and sched_clock on timer 4 */
|
||||
writel(EP93XX_TIMER4_VALUE_HIGH_ENABLE,
|
||||
EP93XX_TIMER4_VALUE_HIGH);
|
||||
clocksource_mmio_init(NULL, "timer4",
|
||||
EP93XX_TIMER4_RATE, 200, 40,
|
||||
ep93xx_clocksource_read);
|
||||
sched_clock_register(ep93xx_read_sched_clock, 40,
|
||||
EP93XX_TIMER4_RATE);
|
||||
|
||||
/* Set up clockevent on timer 3 */
|
||||
if (request_irq(irq, ep93xx_timer_interrupt, flags, "ep93xx timer",
|
||||
&ep93xx_clockevent))
|
||||
pr_err("Failed to request irq %d (ep93xx timer)\n", irq);
|
||||
clockevents_config_and_register(&ep93xx_clockevent,
|
||||
EP93XX_TIMER123_RATE,
|
||||
1,
|
||||
0xffffffffU);
|
||||
}
|
||||
@@ -1,422 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* arch/arm/mach-ep93xx/ts72xx.c
|
||||
* Technologic Systems TS72xx SBC support.
|
||||
*
|
||||
* Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/mtd/platnand.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/flash.h>
|
||||
#include <linux/spi/mmc_spi.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/platform_data/spi-ep93xx.h>
|
||||
#include <linux/gpio/machine.h>
|
||||
|
||||
#include "gpio-ep93xx.h"
|
||||
#include "hardware.h"
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
#include "soc.h"
|
||||
#include "ts72xx.h"
|
||||
|
||||
/*************************************************************************
|
||||
* IO map
|
||||
*************************************************************************/
|
||||
static struct map_desc ts72xx_io_desc[] __initdata = {
|
||||
{
|
||||
.virtual = (unsigned long)TS72XX_MODEL_VIRT_BASE,
|
||||
.pfn = __phys_to_pfn(TS72XX_MODEL_PHYS_BASE),
|
||||
.length = TS72XX_MODEL_SIZE,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)TS72XX_OPTIONS_VIRT_BASE,
|
||||
.pfn = __phys_to_pfn(TS72XX_OPTIONS_PHYS_BASE),
|
||||
.length = TS72XX_OPTIONS_SIZE,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)TS72XX_OPTIONS2_VIRT_BASE,
|
||||
.pfn = __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE),
|
||||
.length = TS72XX_OPTIONS2_SIZE,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)TS72XX_CPLDVER_VIRT_BASE,
|
||||
.pfn = __phys_to_pfn(TS72XX_CPLDVER_PHYS_BASE),
|
||||
.length = TS72XX_CPLDVER_SIZE,
|
||||
.type = MT_DEVICE,
|
||||
}
|
||||
};
|
||||
|
||||
static void __init ts72xx_map_io(void)
|
||||
{
|
||||
ep93xx_map_io();
|
||||
iotable_init(ts72xx_io_desc, ARRAY_SIZE(ts72xx_io_desc));
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* NAND flash
|
||||
*************************************************************************/
|
||||
#define TS72XX_NAND_CONTROL_ADDR_LINE 22 /* 0xN0400000 */
|
||||
#define TS72XX_NAND_BUSY_ADDR_LINE 23 /* 0xN0800000 */
|
||||
|
||||
static void ts72xx_nand_hwcontrol(struct nand_chip *chip,
|
||||
int cmd, unsigned int ctrl)
|
||||
{
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
void __iomem *addr = chip->legacy.IO_ADDR_R;
|
||||
unsigned char bits;
|
||||
|
||||
addr += (1 << TS72XX_NAND_CONTROL_ADDR_LINE);
|
||||
|
||||
bits = __raw_readb(addr) & ~0x07;
|
||||
bits |= (ctrl & NAND_NCE) << 2; /* bit 0 -> bit 2 */
|
||||
bits |= (ctrl & NAND_CLE); /* bit 1 -> bit 1 */
|
||||
bits |= (ctrl & NAND_ALE) >> 2; /* bit 2 -> bit 0 */
|
||||
|
||||
__raw_writeb(bits, addr);
|
||||
}
|
||||
|
||||
if (cmd != NAND_CMD_NONE)
|
||||
__raw_writeb(cmd, chip->legacy.IO_ADDR_W);
|
||||
}
|
||||
|
||||
static int ts72xx_nand_device_ready(struct nand_chip *chip)
|
||||
{
|
||||
void __iomem *addr = chip->legacy.IO_ADDR_R;
|
||||
|
||||
addr += (1 << TS72XX_NAND_BUSY_ADDR_LINE);
|
||||
|
||||
return !!(__raw_readb(addr) & 0x20);
|
||||
}
|
||||
|
||||
#define TS72XX_BOOTROM_PART_SIZE (SZ_16K)
|
||||
#define TS72XX_REDBOOT_PART_SIZE (SZ_2M + SZ_1M)
|
||||
|
||||
static struct mtd_partition ts72xx_nand_parts[] = {
|
||||
{
|
||||
.name = "TS-BOOTROM",
|
||||
.offset = 0,
|
||||
.size = TS72XX_BOOTROM_PART_SIZE,
|
||||
.mask_flags = MTD_WRITEABLE, /* force read-only */
|
||||
}, {
|
||||
.name = "Linux",
|
||||
.offset = MTDPART_OFS_RETAIN,
|
||||
.size = TS72XX_REDBOOT_PART_SIZE,
|
||||
/* leave so much for last partition */
|
||||
}, {
|
||||
.name = "RedBoot",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.size = MTDPART_SIZ_FULL,
|
||||
.mask_flags = MTD_WRITEABLE, /* force read-only */
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_nand_data ts72xx_nand_data = {
|
||||
.chip = {
|
||||
.nr_chips = 1,
|
||||
.chip_offset = 0,
|
||||
.chip_delay = 15,
|
||||
},
|
||||
.ctrl = {
|
||||
.cmd_ctrl = ts72xx_nand_hwcontrol,
|
||||
.dev_ready = ts72xx_nand_device_ready,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource ts72xx_nand_resource[] = {
|
||||
{
|
||||
.start = 0, /* filled in later */
|
||||
.end = 0, /* filled in later */
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device ts72xx_nand_flash = {
|
||||
.name = "gen_nand",
|
||||
.id = -1,
|
||||
.dev.platform_data = &ts72xx_nand_data,
|
||||
.resource = ts72xx_nand_resource,
|
||||
.num_resources = ARRAY_SIZE(ts72xx_nand_resource),
|
||||
};
|
||||
|
||||
static void __init ts72xx_register_flash(struct mtd_partition *parts, int n,
|
||||
resource_size_t start)
|
||||
{
|
||||
/*
|
||||
* TS7200 has NOR flash all other TS72xx board have NAND flash.
|
||||
*/
|
||||
if (board_is_ts7200()) {
|
||||
ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_16M);
|
||||
} else {
|
||||
ts72xx_nand_resource[0].start = start;
|
||||
ts72xx_nand_resource[0].end = start + SZ_16M - 1;
|
||||
|
||||
ts72xx_nand_data.chip.partitions = parts;
|
||||
ts72xx_nand_data.chip.nr_partitions = n;
|
||||
|
||||
platform_device_register(&ts72xx_nand_flash);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* RTC M48T86
|
||||
*************************************************************************/
|
||||
#define TS72XX_RTC_INDEX_PHYS_BASE (EP93XX_CS1_PHYS_BASE + 0x00800000)
|
||||
#define TS72XX_RTC_DATA_PHYS_BASE (EP93XX_CS1_PHYS_BASE + 0x01700000)
|
||||
|
||||
static struct resource ts72xx_rtc_resources[] = {
|
||||
DEFINE_RES_MEM(TS72XX_RTC_INDEX_PHYS_BASE, 0x01),
|
||||
DEFINE_RES_MEM(TS72XX_RTC_DATA_PHYS_BASE, 0x01),
|
||||
};
|
||||
|
||||
static struct platform_device ts72xx_rtc_device = {
|
||||
.name = "rtc-m48t86",
|
||||
.id = -1,
|
||||
.resource = ts72xx_rtc_resources,
|
||||
.num_resources = ARRAY_SIZE(ts72xx_rtc_resources),
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* Watchdog (in CPLD)
|
||||
*************************************************************************/
|
||||
#define TS72XX_WDT_CONTROL_PHYS_BASE (EP93XX_CS2_PHYS_BASE + 0x03800000)
|
||||
#define TS72XX_WDT_FEED_PHYS_BASE (EP93XX_CS2_PHYS_BASE + 0x03c00000)
|
||||
|
||||
static struct resource ts72xx_wdt_resources[] = {
|
||||
DEFINE_RES_MEM(TS72XX_WDT_CONTROL_PHYS_BASE, 0x01),
|
||||
DEFINE_RES_MEM(TS72XX_WDT_FEED_PHYS_BASE, 0x01),
|
||||
};
|
||||
|
||||
static struct platform_device ts72xx_wdt_device = {
|
||||
.name = "ts72xx-wdt",
|
||||
.id = -1,
|
||||
.resource = ts72xx_wdt_resources,
|
||||
.num_resources = ARRAY_SIZE(ts72xx_wdt_resources),
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* ETH
|
||||
*************************************************************************/
|
||||
static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
|
||||
.phy_id = 1,
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* SPI SD/MMC host
|
||||
*************************************************************************/
|
||||
#define BK3_EN_SDCARD_PHYS_BASE 0x12400000
|
||||
#define BK3_EN_SDCARD_PWR 0x0
|
||||
#define BK3_DIS_SDCARD_PWR 0x0C
|
||||
static void bk3_mmc_spi_setpower(struct device *dev, unsigned int vdd)
|
||||
{
|
||||
void __iomem *pwr_sd = ioremap(BK3_EN_SDCARD_PHYS_BASE, SZ_4K);
|
||||
|
||||
if (!pwr_sd) {
|
||||
pr_err("Failed to enable SD card power!");
|
||||
return;
|
||||
}
|
||||
|
||||
pr_debug("%s: SD card pwr %s VDD:0x%x\n", __func__,
|
||||
!!vdd ? "ON" : "OFF", vdd);
|
||||
|
||||
if (!!vdd)
|
||||
__raw_writeb(BK3_EN_SDCARD_PWR, pwr_sd);
|
||||
else
|
||||
__raw_writeb(BK3_DIS_SDCARD_PWR, pwr_sd);
|
||||
|
||||
iounmap(pwr_sd);
|
||||
}
|
||||
|
||||
static struct mmc_spi_platform_data bk3_spi_mmc_data = {
|
||||
.detect_delay = 500,
|
||||
.powerup_msecs = 100,
|
||||
.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
|
||||
.caps = MMC_CAP_NONREMOVABLE,
|
||||
.setpower = bk3_mmc_spi_setpower,
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* SPI Bus - SD card access
|
||||
*************************************************************************/
|
||||
static struct spi_board_info bk3_spi_board_info[] __initdata = {
|
||||
{
|
||||
.modalias = "mmc_spi",
|
||||
.platform_data = &bk3_spi_mmc_data,
|
||||
.max_speed_hz = 7.4E6,
|
||||
.bus_num = 0,
|
||||
.chip_select = 0,
|
||||
.mode = SPI_MODE_0,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* This is a stub -> the FGPIO[3] pin is not connected on the schematic
|
||||
* The all work is performed automatically by !SPI_FRAME (SFRM1) and
|
||||
* goes through CPLD
|
||||
*/
|
||||
static struct gpiod_lookup_table bk3_spi_cs_gpio_table = {
|
||||
.dev_id = "spi0",
|
||||
.table = {
|
||||
GPIO_LOOKUP("F", 3, "cs", GPIO_ACTIVE_LOW),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
static struct ep93xx_spi_info bk3_spi_master __initdata = {
|
||||
.use_dma = 1,
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* TS72XX support code
|
||||
*************************************************************************/
|
||||
#if IS_ENABLED(CONFIG_FPGA_MGR_TS73XX)
|
||||
|
||||
/* Relative to EP93XX_CS1_PHYS_BASE */
|
||||
#define TS73XX_FPGA_LOADER_BASE 0x03c00000
|
||||
|
||||
static struct resource ts73xx_fpga_resources[] = {
|
||||
{
|
||||
.start = EP93XX_CS1_PHYS_BASE + TS73XX_FPGA_LOADER_BASE,
|
||||
.end = EP93XX_CS1_PHYS_BASE + TS73XX_FPGA_LOADER_BASE + 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device ts73xx_fpga_device = {
|
||||
.name = "ts73xx-fpga-mgr",
|
||||
.id = -1,
|
||||
.resource = ts73xx_fpga_resources,
|
||||
.num_resources = ARRAY_SIZE(ts73xx_fpga_resources),
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
* SPI Bus
|
||||
*************************************************************************/
|
||||
static struct spi_board_info ts72xx_spi_devices[] __initdata = {
|
||||
{
|
||||
.modalias = "tmp122",
|
||||
.max_speed_hz = 2 * 1000 * 1000,
|
||||
.bus_num = 0,
|
||||
.chip_select = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table ts72xx_spi_cs_gpio_table = {
|
||||
.dev_id = "spi0",
|
||||
.table = {
|
||||
/* DIO_17 */
|
||||
GPIO_LOOKUP("F", 2, "cs", GPIO_ACTIVE_LOW),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
static struct ep93xx_spi_info ts72xx_spi_info __initdata = {
|
||||
/* Intentionally left blank */
|
||||
};
|
||||
|
||||
static void __init ts72xx_init_machine(void)
|
||||
{
|
||||
ep93xx_init_devices();
|
||||
ts72xx_register_flash(ts72xx_nand_parts, ARRAY_SIZE(ts72xx_nand_parts),
|
||||
is_ts9420_installed() ?
|
||||
EP93XX_CS7_PHYS_BASE : EP93XX_CS6_PHYS_BASE);
|
||||
platform_device_register(&ts72xx_rtc_device);
|
||||
platform_device_register(&ts72xx_wdt_device);
|
||||
|
||||
ep93xx_register_eth(&ts72xx_eth_data, 1);
|
||||
#if IS_ENABLED(CONFIG_FPGA_MGR_TS73XX)
|
||||
if (board_is_ts7300())
|
||||
platform_device_register(&ts73xx_fpga_device);
|
||||
#endif
|
||||
gpiod_add_lookup_table(&ts72xx_spi_cs_gpio_table);
|
||||
ep93xx_register_spi(&ts72xx_spi_info, ts72xx_spi_devices,
|
||||
ARRAY_SIZE(ts72xx_spi_devices));
|
||||
}
|
||||
|
||||
MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
|
||||
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS,
|
||||
.map_io = ts72xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = ts72xx_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
||||
|
||||
/*************************************************************************
|
||||
* EP93xx I2S audio peripheral handling
|
||||
*************************************************************************/
|
||||
static struct resource ep93xx_i2s_resource[] = {
|
||||
DEFINE_RES_MEM(EP93XX_I2S_PHYS_BASE, 0x100),
|
||||
DEFINE_RES_IRQ_NAMED(IRQ_EP93XX_SAI, "spilink i2s slave"),
|
||||
};
|
||||
|
||||
static struct platform_device ep93xx_i2s_device = {
|
||||
.name = "ep93xx-spilink-i2s",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(ep93xx_i2s_resource),
|
||||
.resource = ep93xx_i2s_resource,
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* BK3 support code
|
||||
*************************************************************************/
|
||||
static struct mtd_partition bk3_nand_parts[] = {
|
||||
{
|
||||
.name = "System",
|
||||
.offset = 0x00000000,
|
||||
.size = 0x01e00000,
|
||||
}, {
|
||||
.name = "Data",
|
||||
.offset = 0x01e00000,
|
||||
.size = 0x05f20000
|
||||
}, {
|
||||
.name = "RedBoot",
|
||||
.offset = 0x07d20000,
|
||||
.size = 0x002e0000,
|
||||
.mask_flags = MTD_WRITEABLE, /* force RO */
|
||||
},
|
||||
};
|
||||
|
||||
static void __init bk3_init_machine(void)
|
||||
{
|
||||
ep93xx_init_devices();
|
||||
|
||||
ts72xx_register_flash(bk3_nand_parts, ARRAY_SIZE(bk3_nand_parts),
|
||||
EP93XX_CS6_PHYS_BASE);
|
||||
|
||||
ep93xx_register_eth(&ts72xx_eth_data, 1);
|
||||
|
||||
gpiod_add_lookup_table(&bk3_spi_cs_gpio_table);
|
||||
ep93xx_register_spi(&bk3_spi_master, bk3_spi_board_info,
|
||||
ARRAY_SIZE(bk3_spi_board_info));
|
||||
|
||||
/* Configure ep93xx's I2S to use AC97 pins */
|
||||
ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_I2SONAC97);
|
||||
platform_device_register(&ep93xx_i2s_device);
|
||||
}
|
||||
|
||||
MACHINE_START(BK3, "Liebherr controller BK3.1")
|
||||
/* Maintainer: Lukasz Majewski <lukma@denx.de> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS,
|
||||
.map_io = ts72xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = bk3_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
||||
@@ -1,94 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* arch/arm/mach-ep93xx/include/mach/ts72xx.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* TS72xx memory map:
|
||||
*
|
||||
* virt phys size
|
||||
* febff000 22000000 4K model number register (bits 0-2)
|
||||
* febfe000 22400000 4K options register
|
||||
* febfd000 22800000 4K options register #2
|
||||
* febfc000 23400000 4K CPLD version register
|
||||
*/
|
||||
|
||||
#ifndef __TS72XX_H_
|
||||
#define __TS72XX_H_
|
||||
|
||||
#define TS72XX_MODEL_PHYS_BASE 0x22000000
|
||||
#define TS72XX_MODEL_VIRT_BASE IOMEM(0xfebff000)
|
||||
#define TS72XX_MODEL_SIZE 0x00001000
|
||||
|
||||
#define TS72XX_MODEL_TS7200 0x00
|
||||
#define TS72XX_MODEL_TS7250 0x01
|
||||
#define TS72XX_MODEL_TS7260 0x02
|
||||
#define TS72XX_MODEL_TS7300 0x03
|
||||
#define TS72XX_MODEL_TS7400 0x04
|
||||
#define TS72XX_MODEL_MASK 0x07
|
||||
|
||||
|
||||
#define TS72XX_OPTIONS_PHYS_BASE 0x22400000
|
||||
#define TS72XX_OPTIONS_VIRT_BASE IOMEM(0xfebfe000)
|
||||
#define TS72XX_OPTIONS_SIZE 0x00001000
|
||||
|
||||
#define TS72XX_OPTIONS_COM2_RS485 0x02
|
||||
#define TS72XX_OPTIONS_MAX197 0x01
|
||||
|
||||
|
||||
#define TS72XX_OPTIONS2_PHYS_BASE 0x22800000
|
||||
#define TS72XX_OPTIONS2_VIRT_BASE IOMEM(0xfebfd000)
|
||||
#define TS72XX_OPTIONS2_SIZE 0x00001000
|
||||
|
||||
#define TS72XX_OPTIONS2_TS9420 0x04
|
||||
#define TS72XX_OPTIONS2_TS9420_BOOT 0x02
|
||||
|
||||
#define TS72XX_CPLDVER_PHYS_BASE 0x23400000
|
||||
#define TS72XX_CPLDVER_VIRT_BASE IOMEM(0xfebfc000)
|
||||
#define TS72XX_CPLDVER_SIZE 0x00001000
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
static inline int ts72xx_model(void)
|
||||
{
|
||||
return __raw_readb(TS72XX_MODEL_VIRT_BASE) & TS72XX_MODEL_MASK;
|
||||
}
|
||||
|
||||
static inline int board_is_ts7200(void)
|
||||
{
|
||||
return ts72xx_model() == TS72XX_MODEL_TS7200;
|
||||
}
|
||||
|
||||
static inline int board_is_ts7250(void)
|
||||
{
|
||||
return ts72xx_model() == TS72XX_MODEL_TS7250;
|
||||
}
|
||||
|
||||
static inline int board_is_ts7260(void)
|
||||
{
|
||||
return ts72xx_model() == TS72XX_MODEL_TS7260;
|
||||
}
|
||||
|
||||
static inline int board_is_ts7300(void)
|
||||
{
|
||||
return ts72xx_model() == TS72XX_MODEL_TS7300;
|
||||
}
|
||||
|
||||
static inline int board_is_ts7400(void)
|
||||
{
|
||||
return ts72xx_model() == TS72XX_MODEL_TS7400;
|
||||
}
|
||||
|
||||
static inline int is_max197_installed(void)
|
||||
{
|
||||
return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) &
|
||||
TS72XX_OPTIONS_MAX197);
|
||||
}
|
||||
|
||||
static inline int is_ts9420_installed(void)
|
||||
{
|
||||
return !!(__raw_readb(TS72XX_OPTIONS2_VIRT_BASE) &
|
||||
TS72XX_OPTIONS2_TS9420);
|
||||
}
|
||||
#endif
|
||||
#endif /* __TS72XX_H_ */
|
||||
@@ -1,319 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* arch/arm/mach-ep93xx/vision_ep9307.c
|
||||
* Vision Engraving Systems EP9307 SoM support.
|
||||
*
|
||||
* Copyright (C) 2008-2011 Vision Engraving Systems
|
||||
* H Hartley Sweeten <hsweeten@visionengravers.com>
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/machine.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/platform_data/pca953x.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/flash.h>
|
||||
#include <linux/spi/mmc_spi.h>
|
||||
#include <linux/mmc/host.h>
|
||||
|
||||
#include <sound/cs4271.h>
|
||||
|
||||
#include "hardware.h"
|
||||
#include <linux/platform_data/video-ep93xx.h>
|
||||
#include <linux/platform_data/spi-ep93xx.h>
|
||||
#include "gpio-ep93xx.h"
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
#include "soc.h"
|
||||
|
||||
/*************************************************************************
|
||||
* Static I/O mappings for the FPGA
|
||||
*************************************************************************/
|
||||
#define VISION_PHYS_BASE EP93XX_CS7_PHYS_BASE
|
||||
#define VISION_VIRT_BASE 0xfebff000
|
||||
|
||||
static struct map_desc vision_io_desc[] __initdata = {
|
||||
{
|
||||
.virtual = VISION_VIRT_BASE,
|
||||
.pfn = __phys_to_pfn(VISION_PHYS_BASE),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
};
|
||||
|
||||
static void __init vision_map_io(void)
|
||||
{
|
||||
ep93xx_map_io();
|
||||
|
||||
iotable_init(vision_io_desc, ARRAY_SIZE(vision_io_desc));
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Ethernet
|
||||
*************************************************************************/
|
||||
static struct ep93xx_eth_data vision_eth_data __initdata = {
|
||||
.phy_id = 1,
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* Framebuffer
|
||||
*************************************************************************/
|
||||
#define VISION_LCD_ENABLE EP93XX_GPIO_LINE_EGPIO1
|
||||
|
||||
static int vision_lcd_setup(struct platform_device *pdev)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = gpio_request_one(VISION_LCD_ENABLE, GPIOF_OUT_INIT_HIGH, dev_name(&pdev->dev));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_RAS |
|
||||
EP93XX_SYSCON_DEVCFG_RASONP3 |
|
||||
EP93XX_SYSCON_DEVCFG_EXVC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vision_lcd_teardown(struct platform_device *pdev)
|
||||
{
|
||||
gpio_free(VISION_LCD_ENABLE);
|
||||
}
|
||||
|
||||
static void vision_lcd_blank(int blank_mode, struct fb_info *info)
|
||||
{
|
||||
if (blank_mode)
|
||||
gpio_set_value(VISION_LCD_ENABLE, 0);
|
||||
else
|
||||
gpio_set_value(VISION_LCD_ENABLE, 1);
|
||||
}
|
||||
|
||||
static struct ep93xxfb_mach_info ep93xxfb_info __initdata = {
|
||||
.flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING,
|
||||
.setup = vision_lcd_setup,
|
||||
.teardown = vision_lcd_teardown,
|
||||
.blank = vision_lcd_blank,
|
||||
};
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* GPIO Expanders
|
||||
*************************************************************************/
|
||||
#define PCA9539_74_GPIO_BASE (EP93XX_GPIO_LINE_MAX + 1)
|
||||
#define PCA9539_75_GPIO_BASE (PCA9539_74_GPIO_BASE + 16)
|
||||
#define PCA9539_76_GPIO_BASE (PCA9539_75_GPIO_BASE + 16)
|
||||
#define PCA9539_77_GPIO_BASE (PCA9539_76_GPIO_BASE + 16)
|
||||
|
||||
static struct pca953x_platform_data pca953x_74_gpio_data = {
|
||||
.gpio_base = PCA9539_74_GPIO_BASE,
|
||||
.irq_base = EP93XX_BOARD_IRQ(0),
|
||||
};
|
||||
|
||||
static struct pca953x_platform_data pca953x_75_gpio_data = {
|
||||
.gpio_base = PCA9539_75_GPIO_BASE,
|
||||
.irq_base = -1,
|
||||
};
|
||||
|
||||
static struct pca953x_platform_data pca953x_76_gpio_data = {
|
||||
.gpio_base = PCA9539_76_GPIO_BASE,
|
||||
.irq_base = -1,
|
||||
};
|
||||
|
||||
static struct pca953x_platform_data pca953x_77_gpio_data = {
|
||||
.gpio_base = PCA9539_77_GPIO_BASE,
|
||||
.irq_base = -1,
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* I2C Bus
|
||||
*************************************************************************/
|
||||
|
||||
static struct i2c_board_info vision_i2c_info[] __initdata = {
|
||||
{
|
||||
I2C_BOARD_INFO("isl1208", 0x6f),
|
||||
.irq = IRQ_EP93XX_EXT1,
|
||||
}, {
|
||||
I2C_BOARD_INFO("pca9539", 0x74),
|
||||
.platform_data = &pca953x_74_gpio_data,
|
||||
}, {
|
||||
I2C_BOARD_INFO("pca9539", 0x75),
|
||||
.platform_data = &pca953x_75_gpio_data,
|
||||
}, {
|
||||
I2C_BOARD_INFO("pca9539", 0x76),
|
||||
.platform_data = &pca953x_76_gpio_data,
|
||||
}, {
|
||||
I2C_BOARD_INFO("pca9539", 0x77),
|
||||
.platform_data = &pca953x_77_gpio_data,
|
||||
},
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* SPI CS4271 Audio Codec
|
||||
*************************************************************************/
|
||||
static struct cs4271_platform_data vision_cs4271_data = {
|
||||
/* Intentionally left blank */
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* SPI Flash
|
||||
*************************************************************************/
|
||||
static struct mtd_partition vision_spi_flash_partitions[] = {
|
||||
{
|
||||
.name = "SPI bootstrap",
|
||||
.offset = 0,
|
||||
.size = SZ_4K,
|
||||
}, {
|
||||
.name = "Bootstrap config",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.size = SZ_4K,
|
||||
}, {
|
||||
.name = "System config",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.size = MTDPART_SIZ_FULL,
|
||||
},
|
||||
};
|
||||
|
||||
static struct flash_platform_data vision_spi_flash_data = {
|
||||
.name = "SPI Flash",
|
||||
.parts = vision_spi_flash_partitions,
|
||||
.nr_parts = ARRAY_SIZE(vision_spi_flash_partitions),
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* SPI SD/MMC host
|
||||
*************************************************************************/
|
||||
static struct mmc_spi_platform_data vision_spi_mmc_data = {
|
||||
.detect_delay = 100,
|
||||
.powerup_msecs = 100,
|
||||
.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
|
||||
.caps2 = MMC_CAP2_RO_ACTIVE_HIGH,
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table vision_spi_mmc_gpio_table = {
|
||||
.dev_id = "mmc_spi.2", /* "mmc_spi @ CS2 */
|
||||
.table = {
|
||||
/* Card detect */
|
||||
GPIO_LOOKUP_IDX("B", 7, NULL, 0, GPIO_ACTIVE_LOW),
|
||||
/* Write protect */
|
||||
GPIO_LOOKUP_IDX("F", 0, NULL, 1, GPIO_ACTIVE_HIGH),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* SPI Bus
|
||||
*************************************************************************/
|
||||
static struct spi_board_info vision_spi_board_info[] __initdata = {
|
||||
{
|
||||
.modalias = "cs4271",
|
||||
.platform_data = &vision_cs4271_data,
|
||||
.max_speed_hz = 6000000,
|
||||
.bus_num = 0,
|
||||
.chip_select = 0,
|
||||
.mode = SPI_MODE_3,
|
||||
}, {
|
||||
.modalias = "sst25l",
|
||||
.platform_data = &vision_spi_flash_data,
|
||||
.max_speed_hz = 20000000,
|
||||
.bus_num = 0,
|
||||
.chip_select = 1,
|
||||
.mode = SPI_MODE_3,
|
||||
}, {
|
||||
.modalias = "mmc_spi",
|
||||
.platform_data = &vision_spi_mmc_data,
|
||||
.max_speed_hz = 20000000,
|
||||
.bus_num = 0,
|
||||
.chip_select = 2,
|
||||
.mode = SPI_MODE_3,
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table vision_spi_cs4271_gpio_table = {
|
||||
.dev_id = "spi0.0", /* cs4271 @ CS0 */
|
||||
.table = {
|
||||
/* RESET */
|
||||
GPIO_LOOKUP_IDX("H", 2, NULL, 0, GPIO_ACTIVE_LOW),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table vision_spi_cs_gpio_table = {
|
||||
.dev_id = "spi0",
|
||||
.table = {
|
||||
GPIO_LOOKUP_IDX("A", 6, "cs", 0, GPIO_ACTIVE_LOW),
|
||||
GPIO_LOOKUP_IDX("A", 7, "cs", 1, GPIO_ACTIVE_LOW),
|
||||
GPIO_LOOKUP_IDX("G", 2, "cs", 2, GPIO_ACTIVE_LOW),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
static struct ep93xx_spi_info vision_spi_master __initdata = {
|
||||
.use_dma = 1,
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* I2S Audio
|
||||
*************************************************************************/
|
||||
static struct platform_device vision_audio_device = {
|
||||
.name = "edb93xx-audio",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static void __init vision_register_i2s(void)
|
||||
{
|
||||
ep93xx_register_i2s();
|
||||
platform_device_register(&vision_audio_device);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Machine Initialization
|
||||
*************************************************************************/
|
||||
static void __init vision_init_machine(void)
|
||||
{
|
||||
ep93xx_init_devices();
|
||||
ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_64M);
|
||||
ep93xx_register_eth(&vision_eth_data, 1);
|
||||
ep93xx_register_fb(&ep93xxfb_info);
|
||||
ep93xx_register_pwm(1, 0);
|
||||
|
||||
/*
|
||||
* Request the gpio expander's interrupt gpio line now to prevent
|
||||
* the kernel from doing a WARN in gpiolib:gpio_ensure_requested().
|
||||
*/
|
||||
if (gpio_request_one(EP93XX_GPIO_LINE_F(7), GPIOF_IN, "pca9539:74"))
|
||||
pr_warn("cannot request interrupt gpio for pca9539:74\n");
|
||||
|
||||
vision_i2c_info[1].irq = gpio_to_irq(EP93XX_GPIO_LINE_F(7));
|
||||
|
||||
ep93xx_register_i2c(vision_i2c_info,
|
||||
ARRAY_SIZE(vision_i2c_info));
|
||||
gpiod_add_lookup_table(&vision_spi_cs4271_gpio_table);
|
||||
gpiod_add_lookup_table(&vision_spi_mmc_gpio_table);
|
||||
gpiod_add_lookup_table(&vision_spi_cs_gpio_table);
|
||||
ep93xx_register_spi(&vision_spi_master, vision_spi_board_info,
|
||||
ARRAY_SIZE(vision_spi_board_info));
|
||||
vision_register_i2s();
|
||||
}
|
||||
|
||||
MACHINE_START(VISION_EP9307, "Vision Engraving Systems EP9307")
|
||||
/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS + EP93XX_BOARD_IRQS,
|
||||
.map_io = vision_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = vision_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
||||
@@ -264,8 +264,7 @@ SECTIONS
|
||||
EXIT_DATA
|
||||
}
|
||||
|
||||
RUNTIME_CONST(shift, d_hash_shift)
|
||||
RUNTIME_CONST(ptr, dentry_hashtable)
|
||||
RUNTIME_CONST_VARIABLES
|
||||
|
||||
PERCPU_SECTION(L1_CACHE_BYTES)
|
||||
HYPERVISOR_PERCPU_SECTION
|
||||
|
||||
@@ -466,7 +466,6 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
}
|
||||
|
||||
static const struct file_operations perf_fops = {
|
||||
.llseek = no_llseek,
|
||||
.read = perf_read,
|
||||
.write = perf_write,
|
||||
.unlocked_ioctl = perf_ioctl,
|
||||
|
||||
@@ -76,7 +76,6 @@ static long dbfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
|
||||
static const struct file_operations dbfs_ops = {
|
||||
.read = dbfs_read,
|
||||
.llseek = no_llseek,
|
||||
.unlocked_ioctl = dbfs_ioctl,
|
||||
};
|
||||
|
||||
|
||||
@@ -443,7 +443,6 @@ static const struct file_operations hypfs_file_ops = {
|
||||
.release = hypfs_release,
|
||||
.read_iter = hypfs_read_iter,
|
||||
.write_iter = hypfs_write_iter,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static struct file_system_type hypfs_type = {
|
||||
|
||||
@@ -163,7 +163,6 @@ static const struct file_operations debug_file_ops = {
|
||||
.write = debug_input,
|
||||
.open = debug_open,
|
||||
.release = debug_close,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static struct dentry *debug_debugfs_root_entry;
|
||||
|
||||
@@ -1698,7 +1698,6 @@ static const struct file_operations cfset_fops = {
|
||||
.release = cfset_release,
|
||||
.unlocked_ioctl = cfset_ioctl,
|
||||
.compat_ioctl = cfset_ioctl,
|
||||
.llseek = no_llseek
|
||||
};
|
||||
|
||||
static struct miscdevice cfset_dev = {
|
||||
|
||||
@@ -498,7 +498,6 @@ static const struct file_operations stsi_##fc##_##s1##_##s2##_fs_ops = { \
|
||||
.open = stsi_open_##fc##_##s1##_##s2, \
|
||||
.release = stsi_release, \
|
||||
.read = stsi_read, \
|
||||
.llseek = no_llseek, \
|
||||
};
|
||||
|
||||
static int stsi_release(struct inode *inode, struct file *file)
|
||||
|
||||
@@ -191,8 +191,7 @@ SECTIONS
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
INIT_DATA_SECTION(0x100)
|
||||
|
||||
RUNTIME_CONST(shift, d_hash_shift)
|
||||
RUNTIME_CONST(ptr, dentry_hashtable)
|
||||
RUNTIME_CONST_VARIABLES
|
||||
|
||||
PERCPU_SECTION(0x100)
|
||||
|
||||
|
||||
@@ -657,7 +657,6 @@ static const struct file_operations clp_misc_fops = {
|
||||
.release = clp_misc_release,
|
||||
.unlocked_ioctl = clp_misc_ioctl,
|
||||
.compat_ioctl = clp_misc_ioctl,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static struct miscdevice clp_misc_device = {
|
||||
|
||||
@@ -164,7 +164,6 @@ static const struct file_operations harddog_fops = {
|
||||
.compat_ioctl = compat_ptr_ioctl,
|
||||
.open = harddog_open,
|
||||
.release = harddog_release,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static struct miscdevice harddog_miscdev = {
|
||||
|
||||
@@ -291,7 +291,6 @@ static int hostmixer_release(struct inode *inode, struct file *file)
|
||||
|
||||
static const struct file_operations hostaudio_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.read = hostaudio_read,
|
||||
.write = hostaudio_write,
|
||||
.poll = hostaudio_poll,
|
||||
@@ -304,7 +303,6 @@ static const struct file_operations hostaudio_fops = {
|
||||
|
||||
static const struct file_operations hostmixer_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.unlocked_ioctl = hostmixer_ioctl_mixdev,
|
||||
.open = hostmixer_open_mixdev,
|
||||
.release = hostmixer_release,
|
||||
|
||||
@@ -331,7 +331,6 @@ static const struct file_operations mce_chrdev_ops = {
|
||||
.poll = mce_chrdev_poll,
|
||||
.unlocked_ioctl = mce_chrdev_ioctl,
|
||||
.compat_ioctl = compat_ptr_ioctl,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static struct miscdevice mce_chrdev_device = {
|
||||
|
||||
@@ -1567,7 +1567,6 @@ static int pseudo_lock_dev_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
|
||||
static const struct file_operations pseudo_lock_dev_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.read = NULL,
|
||||
.write = NULL,
|
||||
.open = pseudo_lock_dev_open,
|
||||
|
||||
@@ -357,8 +357,7 @@ SECTIONS
|
||||
PERCPU_SECTION(INTERNODE_CACHE_BYTES)
|
||||
#endif
|
||||
|
||||
RUNTIME_CONST(shift, d_hash_shift)
|
||||
RUNTIME_CONST(ptr, dentry_hashtable)
|
||||
RUNTIME_CONST_VARIABLES
|
||||
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
|
||||
|
||||
@@ -199,7 +199,6 @@ static const struct file_operations erst_dbg_ops = {
|
||||
.read = erst_dbg_read,
|
||||
.write = erst_dbg_write,
|
||||
.unlocked_ioctl = erst_dbg_ioctl,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static struct miscdevice erst_dbg_dev = {
|
||||
|
||||
+48
-57
@@ -44,8 +44,8 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
|
||||
#include <linux/platform_data/dma-ep93xx.h>
|
||||
#include <linux/soc/cirrus/ep93xx.h>
|
||||
|
||||
#define DRV_NAME "ep93xx-ide"
|
||||
@@ -126,7 +126,7 @@ enum {
|
||||
};
|
||||
|
||||
struct ep93xx_pata_data {
|
||||
const struct platform_device *pdev;
|
||||
struct platform_device *pdev;
|
||||
void __iomem *ide_base;
|
||||
struct ata_timing t;
|
||||
bool iordy;
|
||||
@@ -135,9 +135,7 @@ struct ep93xx_pata_data {
|
||||
unsigned long udma_out_phys;
|
||||
|
||||
struct dma_chan *dma_rx_channel;
|
||||
struct ep93xx_dma_data dma_rx_data;
|
||||
struct dma_chan *dma_tx_channel;
|
||||
struct ep93xx_dma_data dma_tx_data;
|
||||
};
|
||||
|
||||
static void ep93xx_pata_clear_regs(void __iomem *base)
|
||||
@@ -637,20 +635,13 @@ static void ep93xx_pata_release_dma(struct ep93xx_pata_data *drv_data)
|
||||
}
|
||||
}
|
||||
|
||||
static bool ep93xx_pata_dma_filter(struct dma_chan *chan, void *filter_param)
|
||||
static int ep93xx_pata_dma_init(struct ep93xx_pata_data *drv_data)
|
||||
{
|
||||
if (ep93xx_dma_chan_is_m2p(chan))
|
||||
return false;
|
||||
|
||||
chan->private = filter_param;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ep93xx_pata_dma_init(struct ep93xx_pata_data *drv_data)
|
||||
{
|
||||
const struct platform_device *pdev = drv_data->pdev;
|
||||
struct platform_device *pdev = drv_data->pdev;
|
||||
struct device *dev = &pdev->dev;
|
||||
dma_cap_mask_t mask;
|
||||
struct dma_slave_config conf;
|
||||
int ret;
|
||||
|
||||
dma_cap_zero(mask);
|
||||
dma_cap_set(DMA_SLAVE, mask);
|
||||
@@ -660,22 +651,16 @@ static void ep93xx_pata_dma_init(struct ep93xx_pata_data *drv_data)
|
||||
* to request only one channel, and reprogram it's direction at
|
||||
* start of new transfer.
|
||||
*/
|
||||
drv_data->dma_rx_data.port = EP93XX_DMA_IDE;
|
||||
drv_data->dma_rx_data.direction = DMA_DEV_TO_MEM;
|
||||
drv_data->dma_rx_data.name = "ep93xx-pata-rx";
|
||||
drv_data->dma_rx_channel = dma_request_channel(mask,
|
||||
ep93xx_pata_dma_filter, &drv_data->dma_rx_data);
|
||||
if (!drv_data->dma_rx_channel)
|
||||
return;
|
||||
drv_data->dma_rx_channel = dma_request_chan(dev, "rx");
|
||||
if (IS_ERR(drv_data->dma_rx_channel))
|
||||
return dev_err_probe(dev, PTR_ERR(drv_data->dma_rx_channel),
|
||||
"rx DMA setup failed\n");
|
||||
|
||||
drv_data->dma_tx_data.port = EP93XX_DMA_IDE;
|
||||
drv_data->dma_tx_data.direction = DMA_MEM_TO_DEV;
|
||||
drv_data->dma_tx_data.name = "ep93xx-pata-tx";
|
||||
drv_data->dma_tx_channel = dma_request_channel(mask,
|
||||
ep93xx_pata_dma_filter, &drv_data->dma_tx_data);
|
||||
if (!drv_data->dma_tx_channel) {
|
||||
dma_release_channel(drv_data->dma_rx_channel);
|
||||
return;
|
||||
drv_data->dma_tx_channel = dma_request_chan(&pdev->dev, "tx");
|
||||
if (IS_ERR(drv_data->dma_tx_channel)) {
|
||||
ret = dev_err_probe(dev, PTR_ERR(drv_data->dma_tx_channel),
|
||||
"tx DMA setup failed\n");
|
||||
goto fail_release_rx;
|
||||
}
|
||||
|
||||
/* Configure receive channel direction and source address */
|
||||
@@ -683,10 +668,10 @@ static void ep93xx_pata_dma_init(struct ep93xx_pata_data *drv_data)
|
||||
conf.direction = DMA_DEV_TO_MEM;
|
||||
conf.src_addr = drv_data->udma_in_phys;
|
||||
conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
|
||||
if (dmaengine_slave_config(drv_data->dma_rx_channel, &conf)) {
|
||||
dev_err(&pdev->dev, "failed to configure rx dma channel\n");
|
||||
ep93xx_pata_release_dma(drv_data);
|
||||
return;
|
||||
ret = dmaengine_slave_config(drv_data->dma_rx_channel, &conf);
|
||||
if (ret) {
|
||||
dev_err_probe(dev, ret, "failed to configure rx dma channel");
|
||||
goto fail_release_dma;
|
||||
}
|
||||
|
||||
/* Configure transmit channel direction and destination address */
|
||||
@@ -694,10 +679,20 @@ static void ep93xx_pata_dma_init(struct ep93xx_pata_data *drv_data)
|
||||
conf.direction = DMA_MEM_TO_DEV;
|
||||
conf.dst_addr = drv_data->udma_out_phys;
|
||||
conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
|
||||
if (dmaengine_slave_config(drv_data->dma_tx_channel, &conf)) {
|
||||
dev_err(&pdev->dev, "failed to configure tx dma channel\n");
|
||||
ep93xx_pata_release_dma(drv_data);
|
||||
ret = dmaengine_slave_config(drv_data->dma_tx_channel, &conf);
|
||||
if (ret) {
|
||||
dev_err_probe(dev, ret, "failed to configure tx dma channel");
|
||||
goto fail_release_dma;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail_release_rx:
|
||||
dma_release_channel(drv_data->dma_rx_channel);
|
||||
fail_release_dma:
|
||||
ep93xx_pata_release_dma(drv_data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ep93xx_pata_dma_start(struct ata_queued_cmd *qc)
|
||||
@@ -925,34 +920,26 @@ static int ep93xx_pata_probe(struct platform_device *pdev)
|
||||
void __iomem *ide_base;
|
||||
int err;
|
||||
|
||||
err = ep93xx_ide_acquire_gpio(pdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* INT[3] (IRQ_EP93XX_EXT3) line connected as pull down */
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
err = irq;
|
||||
goto err_rel_gpio;
|
||||
}
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
ide_base = devm_platform_get_and_ioremap_resource(pdev, 0, &mem_res);
|
||||
if (IS_ERR(ide_base)) {
|
||||
err = PTR_ERR(ide_base);
|
||||
goto err_rel_gpio;
|
||||
}
|
||||
if (IS_ERR(ide_base))
|
||||
return PTR_ERR(ide_base);
|
||||
|
||||
drv_data = devm_kzalloc(&pdev->dev, sizeof(*drv_data), GFP_KERNEL);
|
||||
if (!drv_data) {
|
||||
err = -ENOMEM;
|
||||
goto err_rel_gpio;
|
||||
}
|
||||
if (!drv_data)
|
||||
return -ENOMEM;
|
||||
|
||||
drv_data->pdev = pdev;
|
||||
drv_data->ide_base = ide_base;
|
||||
drv_data->udma_in_phys = mem_res->start + IDEUDMADATAIN;
|
||||
drv_data->udma_out_phys = mem_res->start + IDEUDMADATAOUT;
|
||||
ep93xx_pata_dma_init(drv_data);
|
||||
err = ep93xx_pata_dma_init(drv_data);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* allocate host */
|
||||
host = ata_host_alloc(&pdev->dev, 1);
|
||||
@@ -1003,8 +990,6 @@ static int ep93xx_pata_probe(struct platform_device *pdev)
|
||||
|
||||
err_rel_dma:
|
||||
ep93xx_pata_release_dma(drv_data);
|
||||
err_rel_gpio:
|
||||
ep93xx_ide_release_gpio(pdev);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1016,12 +1001,18 @@ static void ep93xx_pata_remove(struct platform_device *pdev)
|
||||
ata_host_detach(host);
|
||||
ep93xx_pata_release_dma(drv_data);
|
||||
ep93xx_pata_clear_regs(drv_data->ide_base);
|
||||
ep93xx_ide_release_gpio(pdev);
|
||||
}
|
||||
|
||||
static const struct of_device_id ep93xx_pata_of_ids[] = {
|
||||
{ .compatible = "cirrus,ep9312-pata" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ep93xx_pata_of_ids);
|
||||
|
||||
static struct platform_driver ep93xx_pata_platform_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = ep93xx_pata_of_ids,
|
||||
},
|
||||
.probe = ep93xx_pata_probe,
|
||||
.remove_new = ep93xx_pata_remove,
|
||||
|
||||
@@ -526,7 +526,6 @@ static const struct file_operations charlcd_fops = {
|
||||
.write = charlcd_write,
|
||||
.open = charlcd_open,
|
||||
.release = charlcd_release,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static struct miscdevice charlcd_dev = {
|
||||
|
||||
@@ -346,8 +346,7 @@ attribute_container_device_trigger_safe(struct device *dev,
|
||||
* @fn: the function to execute for each classdev.
|
||||
*
|
||||
* This function is for executing a trigger when you need to know both
|
||||
* the container and the classdev. If you only care about the
|
||||
* container, then use attribute_container_trigger() instead.
|
||||
* the container and the classdev.
|
||||
*/
|
||||
void
|
||||
attribute_container_device_trigger(struct device *dev,
|
||||
@@ -378,33 +377,6 @@ attribute_container_device_trigger(struct device *dev,
|
||||
mutex_unlock(&attribute_container_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* attribute_container_trigger - trigger a function for each matching container
|
||||
*
|
||||
* @dev: The generic device to activate the trigger for
|
||||
* @fn: the function to trigger
|
||||
*
|
||||
* This routine triggers a function that only needs to know the
|
||||
* matching containers (not the classdev) associated with a device.
|
||||
* It is more lightweight than attribute_container_device_trigger, so
|
||||
* should be used in preference unless the triggering function
|
||||
* actually needs to know the classdev.
|
||||
*/
|
||||
void
|
||||
attribute_container_trigger(struct device *dev,
|
||||
int (*fn)(struct attribute_container *,
|
||||
struct device *))
|
||||
{
|
||||
struct attribute_container *cont;
|
||||
|
||||
mutex_lock(&attribute_container_mutex);
|
||||
list_for_each_entry(cont, &attribute_container_list, node) {
|
||||
if (cont->match(cont, dev))
|
||||
fn(cont, dev);
|
||||
}
|
||||
mutex_unlock(&attribute_container_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* attribute_container_add_attrs - add attributes
|
||||
*
|
||||
@@ -458,24 +430,6 @@ attribute_container_add_class_device(struct device *classdev)
|
||||
return attribute_container_add_attrs(classdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* attribute_container_add_class_device_adapter - simple adapter for triggers
|
||||
*
|
||||
* @cont: the container to register.
|
||||
* @dev: the generic device to activate the trigger for
|
||||
* @classdev: the class device to add
|
||||
*
|
||||
* This function is identical to attribute_container_add_class_device except
|
||||
* that it is designed to be called from the triggers
|
||||
*/
|
||||
int
|
||||
attribute_container_add_class_device_adapter(struct attribute_container *cont,
|
||||
struct device *dev,
|
||||
struct device *classdev)
|
||||
{
|
||||
return attribute_container_add_class_device(classdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* attribute_container_remove_attrs - remove any attribute files
|
||||
*
|
||||
|
||||
@@ -352,7 +352,7 @@ EXPORT_SYMBOL_GPL(__auxiliary_device_add);
|
||||
*/
|
||||
struct auxiliary_device *auxiliary_find_device(struct device *start,
|
||||
const void *data,
|
||||
int (*match)(struct device *dev, const void *data))
|
||||
device_match_t match)
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
|
||||
+1
-1
@@ -145,7 +145,7 @@ void auxiliary_bus_init(void);
|
||||
static inline void auxiliary_bus_init(void) { }
|
||||
#endif
|
||||
|
||||
struct kobject *virtual_device_parent(struct device *dev);
|
||||
struct kobject *virtual_device_parent(void);
|
||||
|
||||
int bus_add_device(struct device *dev);
|
||||
void bus_probe_device(struct device *dev);
|
||||
|
||||
+14
-5
@@ -152,7 +152,8 @@ static ssize_t bus_attr_show(struct kobject *kobj, struct attribute *attr,
|
||||
{
|
||||
struct bus_attribute *bus_attr = to_bus_attr(attr);
|
||||
struct subsys_private *subsys_priv = to_subsys_private(kobj);
|
||||
ssize_t ret = 0;
|
||||
/* return -EIO for reading a bus attribute without show() */
|
||||
ssize_t ret = -EIO;
|
||||
|
||||
if (bus_attr->show)
|
||||
ret = bus_attr->show(subsys_priv->bus, buf);
|
||||
@@ -164,7 +165,8 @@ static ssize_t bus_attr_store(struct kobject *kobj, struct attribute *attr,
|
||||
{
|
||||
struct bus_attribute *bus_attr = to_bus_attr(attr);
|
||||
struct subsys_private *subsys_priv = to_subsys_private(kobj);
|
||||
ssize_t ret = 0;
|
||||
/* return -EIO for writing a bus attribute without store() */
|
||||
ssize_t ret = -EIO;
|
||||
|
||||
if (bus_attr->store)
|
||||
ret = bus_attr->store(subsys_priv->bus, buf, count);
|
||||
@@ -389,7 +391,7 @@ EXPORT_SYMBOL_GPL(bus_for_each_dev);
|
||||
*/
|
||||
struct device *bus_find_device(const struct bus_type *bus,
|
||||
struct device *start, const void *data,
|
||||
int (*match)(struct device *dev, const void *data))
|
||||
device_match_t match)
|
||||
{
|
||||
struct subsys_private *sp = bus_to_subsys(bus);
|
||||
struct klist_iter i;
|
||||
@@ -920,6 +922,8 @@ bus_devices_fail:
|
||||
bus_remove_file(bus, &bus_attr_uevent);
|
||||
bus_uevent_fail:
|
||||
kset_unregister(&priv->subsys);
|
||||
/* Above kset_unregister() will kfree @priv */
|
||||
priv = NULL;
|
||||
out:
|
||||
kfree(priv);
|
||||
return retval;
|
||||
@@ -1294,7 +1298,7 @@ int subsys_virtual_register(const struct bus_type *subsys,
|
||||
{
|
||||
struct kobject *virtual_dir;
|
||||
|
||||
virtual_dir = virtual_device_parent(NULL);
|
||||
virtual_dir = virtual_device_parent();
|
||||
if (!virtual_dir)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1385,8 +1389,13 @@ int __init buses_init(void)
|
||||
return -ENOMEM;
|
||||
|
||||
system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj);
|
||||
if (!system_kset)
|
||||
if (!system_kset) {
|
||||
/* Do error handling here as devices_init() do */
|
||||
kset_unregister(bus_kset);
|
||||
bus_kset = NULL;
|
||||
pr_err("%s: failed to create and add kset 'bus'\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+12
-2
@@ -183,6 +183,17 @@ int class_register(const struct class *cls)
|
||||
|
||||
pr_debug("device class '%s': registering\n", cls->name);
|
||||
|
||||
if (cls->ns_type && !cls->namespace) {
|
||||
pr_err("%s: class '%s' does not have namespace\n",
|
||||
__func__, cls->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!cls->ns_type && cls->namespace) {
|
||||
pr_err("%s: class '%s' does not have ns_type\n",
|
||||
__func__, cls->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cp = kzalloc(sizeof(*cp), GFP_KERNEL);
|
||||
if (!cp)
|
||||
return -ENOMEM;
|
||||
@@ -433,8 +444,7 @@ EXPORT_SYMBOL_GPL(class_for_each_device);
|
||||
* code. There's no locking restriction.
|
||||
*/
|
||||
struct device *class_find_device(const struct class *class, const struct device *start,
|
||||
const void *data,
|
||||
int (*match)(struct device *, const void *))
|
||||
const void *data, device_match_t match)
|
||||
{
|
||||
struct subsys_private *sp = class_to_subsys(class);
|
||||
struct class_dev_iter iter;
|
||||
|
||||
+83
-85
@@ -9,29 +9,30 @@
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-map-ops.h> /* for dma_default_coherent */
|
||||
#include <linux/err.h>
|
||||
#include <linux/fwnode.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/kstrtox.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/sched/signal.h>
|
||||
#include <linux/sched/mm.h>
|
||||
#include <linux/sched/signal.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string_helpers.h>
|
||||
#include <linux/swiotlb.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/dma-map-ops.h> /* for dma_default_coherent */
|
||||
|
||||
#include "base.h"
|
||||
#include "physical_location.h"
|
||||
@@ -97,12 +98,9 @@ static int __fwnode_link_add(struct fwnode_handle *con,
|
||||
int fwnode_link_add(struct fwnode_handle *con, struct fwnode_handle *sup,
|
||||
u8 flags)
|
||||
{
|
||||
int ret;
|
||||
guard(mutex)(&fwnode_link_lock);
|
||||
|
||||
mutex_lock(&fwnode_link_lock);
|
||||
ret = __fwnode_link_add(con, sup, flags);
|
||||
mutex_unlock(&fwnode_link_lock);
|
||||
return ret;
|
||||
return __fwnode_link_add(con, sup, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,10 +141,10 @@ static void fwnode_links_purge_suppliers(struct fwnode_handle *fwnode)
|
||||
{
|
||||
struct fwnode_link *link, *tmp;
|
||||
|
||||
mutex_lock(&fwnode_link_lock);
|
||||
guard(mutex)(&fwnode_link_lock);
|
||||
|
||||
list_for_each_entry_safe(link, tmp, &fwnode->suppliers, c_hook)
|
||||
__fwnode_link_del(link);
|
||||
mutex_unlock(&fwnode_link_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,10 +157,10 @@ static void fwnode_links_purge_consumers(struct fwnode_handle *fwnode)
|
||||
{
|
||||
struct fwnode_link *link, *tmp;
|
||||
|
||||
mutex_lock(&fwnode_link_lock);
|
||||
guard(mutex)(&fwnode_link_lock);
|
||||
|
||||
list_for_each_entry_safe(link, tmp, &fwnode->consumers, s_hook)
|
||||
__fwnode_link_del(link);
|
||||
mutex_unlock(&fwnode_link_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -563,20 +561,11 @@ static struct class devlink_class = {
|
||||
|
||||
static int devlink_add_symlinks(struct device *dev)
|
||||
{
|
||||
char *buf_con __free(kfree) = NULL, *buf_sup __free(kfree) = NULL;
|
||||
int ret;
|
||||
size_t len;
|
||||
struct device_link *link = to_devlink(dev);
|
||||
struct device *sup = link->supplier;
|
||||
struct device *con = link->consumer;
|
||||
char *buf;
|
||||
|
||||
len = max(strlen(dev_bus_name(sup)) + strlen(dev_name(sup)),
|
||||
strlen(dev_bus_name(con)) + strlen(dev_name(con)));
|
||||
len += strlen(":");
|
||||
len += strlen("supplier:") + 1;
|
||||
buf = kzalloc(len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = sysfs_create_link(&link->link_dev.kobj, &sup->kobj, "supplier");
|
||||
if (ret)
|
||||
@@ -586,58 +575,64 @@ static int devlink_add_symlinks(struct device *dev)
|
||||
if (ret)
|
||||
goto err_con;
|
||||
|
||||
snprintf(buf, len, "consumer:%s:%s", dev_bus_name(con), dev_name(con));
|
||||
ret = sysfs_create_link(&sup->kobj, &link->link_dev.kobj, buf);
|
||||
buf_con = kasprintf(GFP_KERNEL, "consumer:%s:%s", dev_bus_name(con), dev_name(con));
|
||||
if (!buf_con) {
|
||||
ret = -ENOMEM;
|
||||
goto err_con_dev;
|
||||
}
|
||||
|
||||
ret = sysfs_create_link(&sup->kobj, &link->link_dev.kobj, buf_con);
|
||||
if (ret)
|
||||
goto err_con_dev;
|
||||
|
||||
snprintf(buf, len, "supplier:%s:%s", dev_bus_name(sup), dev_name(sup));
|
||||
ret = sysfs_create_link(&con->kobj, &link->link_dev.kobj, buf);
|
||||
buf_sup = kasprintf(GFP_KERNEL, "supplier:%s:%s", dev_bus_name(sup), dev_name(sup));
|
||||
if (!buf_sup) {
|
||||
ret = -ENOMEM;
|
||||
goto err_sup_dev;
|
||||
}
|
||||
|
||||
ret = sysfs_create_link(&con->kobj, &link->link_dev.kobj, buf_sup);
|
||||
if (ret)
|
||||
goto err_sup_dev;
|
||||
|
||||
goto out;
|
||||
|
||||
err_sup_dev:
|
||||
snprintf(buf, len, "consumer:%s:%s", dev_bus_name(con), dev_name(con));
|
||||
sysfs_remove_link(&sup->kobj, buf);
|
||||
sysfs_remove_link(&sup->kobj, buf_con);
|
||||
err_con_dev:
|
||||
sysfs_remove_link(&link->link_dev.kobj, "consumer");
|
||||
err_con:
|
||||
sysfs_remove_link(&link->link_dev.kobj, "supplier");
|
||||
out:
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void devlink_remove_symlinks(struct device *dev)
|
||||
{
|
||||
char *buf_con __free(kfree) = NULL, *buf_sup __free(kfree) = NULL;
|
||||
struct device_link *link = to_devlink(dev);
|
||||
size_t len;
|
||||
struct device *sup = link->supplier;
|
||||
struct device *con = link->consumer;
|
||||
char *buf;
|
||||
|
||||
sysfs_remove_link(&link->link_dev.kobj, "consumer");
|
||||
sysfs_remove_link(&link->link_dev.kobj, "supplier");
|
||||
|
||||
len = max(strlen(dev_bus_name(sup)) + strlen(dev_name(sup)),
|
||||
strlen(dev_bus_name(con)) + strlen(dev_name(con)));
|
||||
len += strlen(":");
|
||||
len += strlen("supplier:") + 1;
|
||||
buf = kzalloc(len, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
WARN(1, "Unable to properly free device link symlinks!\n");
|
||||
return;
|
||||
if (device_is_registered(con)) {
|
||||
buf_sup = kasprintf(GFP_KERNEL, "supplier:%s:%s", dev_bus_name(sup), dev_name(sup));
|
||||
if (!buf_sup)
|
||||
goto out;
|
||||
sysfs_remove_link(&con->kobj, buf_sup);
|
||||
}
|
||||
|
||||
if (device_is_registered(con)) {
|
||||
snprintf(buf, len, "supplier:%s:%s", dev_bus_name(sup), dev_name(sup));
|
||||
sysfs_remove_link(&con->kobj, buf);
|
||||
}
|
||||
snprintf(buf, len, "consumer:%s:%s", dev_bus_name(con), dev_name(con));
|
||||
sysfs_remove_link(&sup->kobj, buf);
|
||||
kfree(buf);
|
||||
buf_con = kasprintf(GFP_KERNEL, "consumer:%s:%s", dev_bus_name(con), dev_name(con));
|
||||
if (!buf_con)
|
||||
goto out;
|
||||
sysfs_remove_link(&sup->kobj, buf_con);
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
WARN(1, "Unable to properly free device link symlinks!\n");
|
||||
}
|
||||
|
||||
static struct class_interface devlink_class_intf = {
|
||||
@@ -678,6 +673,9 @@ postcore_initcall(devlink_class_init);
|
||||
* @supplier: Supplier end of the link.
|
||||
* @flags: Link flags.
|
||||
*
|
||||
* Return: On success, a device_link struct will be returned.
|
||||
* On error or invalid flag settings, NULL will be returned.
|
||||
*
|
||||
* The caller is responsible for the proper synchronization of the link creation
|
||||
* with runtime PM. First, setting the DL_FLAG_PM_RUNTIME flag will cause the
|
||||
* runtime PM framework to take the link into account. Second, if the
|
||||
@@ -1061,20 +1059,16 @@ int device_links_check_suppliers(struct device *dev)
|
||||
* Device waiting for supplier to become available is not allowed to
|
||||
* probe.
|
||||
*/
|
||||
mutex_lock(&fwnode_link_lock);
|
||||
sup_fw = fwnode_links_check_suppliers(dev->fwnode);
|
||||
if (sup_fw) {
|
||||
if (!dev_is_best_effort(dev)) {
|
||||
fwnode_ret = -EPROBE_DEFER;
|
||||
dev_err_probe(dev, -EPROBE_DEFER,
|
||||
"wait for supplier %pfwf\n", sup_fw);
|
||||
} else {
|
||||
fwnode_ret = -EAGAIN;
|
||||
scoped_guard(mutex, &fwnode_link_lock) {
|
||||
sup_fw = fwnode_links_check_suppliers(dev->fwnode);
|
||||
if (sup_fw) {
|
||||
if (dev_is_best_effort(dev))
|
||||
fwnode_ret = -EAGAIN;
|
||||
else
|
||||
return dev_err_probe(dev, -EPROBE_DEFER,
|
||||
"wait for supplier %pfwf\n", sup_fw);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&fwnode_link_lock);
|
||||
if (fwnode_ret == -EPROBE_DEFER)
|
||||
return fwnode_ret;
|
||||
|
||||
device_links_write_lock();
|
||||
|
||||
@@ -1093,10 +1087,8 @@ int device_links_check_suppliers(struct device *dev)
|
||||
}
|
||||
|
||||
device_links_missing_supplier(dev);
|
||||
dev_err_probe(dev, -EPROBE_DEFER,
|
||||
"supplier %s not ready\n",
|
||||
dev_name(link->supplier));
|
||||
ret = -EPROBE_DEFER;
|
||||
ret = dev_err_probe(dev, -EPROBE_DEFER,
|
||||
"supplier %s not ready\n", dev_name(link->supplier));
|
||||
break;
|
||||
}
|
||||
WRITE_ONCE(link->status, DL_STATE_CONSUMER_PROBE);
|
||||
@@ -1249,9 +1241,8 @@ static ssize_t waiting_for_supplier_show(struct device *dev,
|
||||
bool val;
|
||||
|
||||
device_lock(dev);
|
||||
mutex_lock(&fwnode_link_lock);
|
||||
val = !!fwnode_links_check_suppliers(dev->fwnode);
|
||||
mutex_unlock(&fwnode_link_lock);
|
||||
scoped_guard(mutex, &fwnode_link_lock)
|
||||
val = !!fwnode_links_check_suppliers(dev->fwnode);
|
||||
device_unlock(dev);
|
||||
return sysfs_emit(buf, "%u\n", val);
|
||||
}
|
||||
@@ -1324,13 +1315,15 @@ void device_links_driver_bound(struct device *dev)
|
||||
*/
|
||||
if (dev->fwnode && dev->fwnode->dev == dev) {
|
||||
struct fwnode_handle *child;
|
||||
|
||||
fwnode_links_purge_suppliers(dev->fwnode);
|
||||
mutex_lock(&fwnode_link_lock);
|
||||
|
||||
guard(mutex)(&fwnode_link_lock);
|
||||
|
||||
fwnode_for_each_available_child_node(dev->fwnode, child)
|
||||
__fw_devlink_pickup_dangling_consumers(child,
|
||||
dev->fwnode);
|
||||
__fw_devlink_link_to_consumers(dev);
|
||||
mutex_unlock(&fwnode_link_lock);
|
||||
}
|
||||
device_remove_file(dev, &dev_attr_waiting_for_supplier);
|
||||
|
||||
@@ -2339,10 +2332,10 @@ static void fw_devlink_link_device(struct device *dev)
|
||||
|
||||
fw_devlink_parse_fwtree(fwnode);
|
||||
|
||||
mutex_lock(&fwnode_link_lock);
|
||||
guard(mutex)(&fwnode_link_lock);
|
||||
|
||||
__fw_devlink_link_to_consumers(dev);
|
||||
__fw_devlink_link_to_suppliers(dev, fwnode);
|
||||
mutex_unlock(&fwnode_link_lock);
|
||||
}
|
||||
|
||||
/* Device links support end. */
|
||||
@@ -2591,7 +2584,7 @@ static const void *device_namespace(const struct kobject *kobj)
|
||||
const struct device *dev = kobj_to_dev(kobj);
|
||||
const void *ns = NULL;
|
||||
|
||||
if (dev->class && dev->class->ns_type)
|
||||
if (dev->class && dev->class->namespace)
|
||||
ns = dev->class->namespace(dev);
|
||||
|
||||
return ns;
|
||||
@@ -3170,7 +3163,7 @@ void device_initialize(struct device *dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_initialize);
|
||||
|
||||
struct kobject *virtual_device_parent(struct device *dev)
|
||||
struct kobject *virtual_device_parent(void)
|
||||
{
|
||||
static struct kobject *virtual_dir = NULL;
|
||||
|
||||
@@ -3248,7 +3241,7 @@ static struct kobject *get_device_parent(struct device *dev,
|
||||
* in a "glue" directory to prevent namespace collisions.
|
||||
*/
|
||||
if (parent == NULL)
|
||||
parent_kobj = virtual_device_parent(dev);
|
||||
parent_kobj = virtual_device_parent();
|
||||
else if (parent->class && !dev->class->ns_type) {
|
||||
subsys_put(sp);
|
||||
return &parent->kobj;
|
||||
@@ -4003,7 +3996,7 @@ int device_for_each_child(struct device *parent, void *data,
|
||||
struct device *child;
|
||||
int error = 0;
|
||||
|
||||
if (!parent->p)
|
||||
if (!parent || !parent->p)
|
||||
return 0;
|
||||
|
||||
klist_iter_init(&parent->p->klist_children, &i);
|
||||
@@ -4033,7 +4026,7 @@ int device_for_each_child_reverse(struct device *parent, void *data,
|
||||
struct device *child;
|
||||
int error = 0;
|
||||
|
||||
if (!parent->p)
|
||||
if (!parent || !parent->p)
|
||||
return 0;
|
||||
|
||||
klist_iter_init(&parent->p->klist_children, &i);
|
||||
@@ -4067,7 +4060,7 @@ struct device *device_find_child(struct device *parent, void *data,
|
||||
struct klist_iter i;
|
||||
struct device *child;
|
||||
|
||||
if (!parent)
|
||||
if (!parent || !parent->p)
|
||||
return NULL;
|
||||
|
||||
klist_iter_init(&parent->p->klist_children, &i);
|
||||
@@ -4515,9 +4508,11 @@ EXPORT_SYMBOL_GPL(device_destroy);
|
||||
*/
|
||||
int device_rename(struct device *dev, const char *new_name)
|
||||
{
|
||||
struct subsys_private *sp = NULL;
|
||||
struct kobject *kobj = &dev->kobj;
|
||||
char *old_device_name = NULL;
|
||||
int error;
|
||||
bool is_link_renamed = false;
|
||||
|
||||
dev = get_device(dev);
|
||||
if (!dev)
|
||||
@@ -4532,7 +4527,7 @@ int device_rename(struct device *dev, const char *new_name)
|
||||
}
|
||||
|
||||
if (dev->class) {
|
||||
struct subsys_private *sp = class_to_subsys(dev->class);
|
||||
sp = class_to_subsys(dev->class);
|
||||
|
||||
if (!sp) {
|
||||
error = -EINVAL;
|
||||
@@ -4541,16 +4536,19 @@ int device_rename(struct device *dev, const char *new_name)
|
||||
|
||||
error = sysfs_rename_link_ns(&sp->subsys.kobj, kobj, old_device_name,
|
||||
new_name, kobject_namespace(kobj));
|
||||
subsys_put(sp);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
is_link_renamed = true;
|
||||
}
|
||||
|
||||
error = kobject_rename(kobj, new_name);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
if (error && is_link_renamed)
|
||||
sysfs_rename_link_ns(&sp->subsys.kobj, kobj, new_name,
|
||||
old_device_name, kobject_namespace(kobj));
|
||||
subsys_put(sp);
|
||||
|
||||
put_device(dev);
|
||||
|
||||
kfree(old_device_name);
|
||||
@@ -4872,7 +4870,7 @@ set_dev_info(const struct device *dev, struct dev_printk_info *dev_info)
|
||||
else
|
||||
return;
|
||||
|
||||
strscpy(dev_info->subsystem, subsys, sizeof(dev_info->subsystem));
|
||||
strscpy(dev_info->subsystem, subsys);
|
||||
|
||||
/*
|
||||
* Add device identifier DEVICE=:
|
||||
|
||||
+1
-1
@@ -248,7 +248,7 @@ static int deferred_devs_show(struct seq_file *s, void *data)
|
||||
|
||||
list_for_each_entry(curr, &deferred_probe_pending_list, deferred_probe)
|
||||
seq_printf(s, "%s\t%s", dev_name(curr->device),
|
||||
curr->device->p->deferred_probe_reason ?: "\n");
|
||||
curr->deferred_probe_reason ?: "\n");
|
||||
|
||||
mutex_unlock(&deferred_probe_mutex);
|
||||
|
||||
|
||||
@@ -1231,6 +1231,6 @@ void devm_free_percpu(struct device *dev, void __percpu *pdata)
|
||||
* devm_free_pages() does.
|
||||
*/
|
||||
WARN_ON(devres_release(dev, devm_percpu_release, devm_percpu_match,
|
||||
(__force void *)pdata));
|
||||
(void *)(__force unsigned long)pdata));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_free_percpu);
|
||||
|
||||
@@ -150,7 +150,7 @@ EXPORT_SYMBOL_GPL(driver_for_each_device);
|
||||
*/
|
||||
struct device *driver_find_device(const struct device_driver *drv,
|
||||
struct device *start, const void *data,
|
||||
int (*match)(struct device *dev, const void *data))
|
||||
device_match_t match)
|
||||
{
|
||||
struct klist_iter i;
|
||||
struct device *dev;
|
||||
|
||||
@@ -849,6 +849,26 @@ static void fw_log_firmware_info(const struct firmware *fw, const char *name,
|
||||
{}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Reject firmware file names with ".." path components.
|
||||
* There are drivers that construct firmware file names from device-supplied
|
||||
* strings, and we don't want some device to be able to tell us "I would like to
|
||||
* be sent my firmware from ../../../etc/shadow, please".
|
||||
*
|
||||
* Search for ".." surrounded by either '/' or start/end of string.
|
||||
*
|
||||
* This intentionally only looks at the firmware name, not at the firmware base
|
||||
* directory or at symlink contents.
|
||||
*/
|
||||
static bool name_contains_dotdot(const char *name)
|
||||
{
|
||||
size_t name_len = strlen(name);
|
||||
|
||||
return strcmp(name, "..") == 0 || strncmp(name, "../", 3) == 0 ||
|
||||
strstr(name, "/../") != NULL ||
|
||||
(name_len >= 3 && strcmp(name+name_len-3, "/..") == 0);
|
||||
}
|
||||
|
||||
/* called from request_firmware() and request_firmware_work_func() */
|
||||
static int
|
||||
_request_firmware(const struct firmware **firmware_p, const char *name,
|
||||
@@ -869,6 +889,14 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (name_contains_dotdot(name)) {
|
||||
dev_warn(device,
|
||||
"Firmware load for '%s' refused, path contains '..' component\n",
|
||||
name);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = _request_firmware_prepare(&fw, name, device, buf, size,
|
||||
offset, opt_flags);
|
||||
if (ret <= 0) /* error or already assigned */
|
||||
@@ -946,6 +974,8 @@ out:
|
||||
* @name will be used as $FIRMWARE in the uevent environment and
|
||||
* should be distinctive enough not to be confused with any other
|
||||
* firmware image for this or any other device.
|
||||
* It must not contain any ".." path components - "foo/bar..bin" is
|
||||
* allowed, but "foo/../bar.bin" is not.
|
||||
*
|
||||
* Caller must hold the reference count of @device.
|
||||
*
|
||||
|
||||
@@ -66,27 +66,31 @@ int module_add_driver(struct module *mod, const struct device_driver *drv)
|
||||
driver_name = make_driver_name(drv);
|
||||
if (!driver_name) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
goto out_remove_kobj;
|
||||
}
|
||||
|
||||
module_create_drivers_dir(mk);
|
||||
if (!mk->drivers_dir) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
goto out_free_driver_name;
|
||||
}
|
||||
|
||||
ret = sysfs_create_link(mk->drivers_dir, &drv->p->kobj, driver_name);
|
||||
if (ret)
|
||||
goto out;
|
||||
goto out_remove_drivers_dir;
|
||||
|
||||
kfree(driver_name);
|
||||
|
||||
return 0;
|
||||
out:
|
||||
sysfs_remove_link(&drv->p->kobj, "module");
|
||||
|
||||
out_remove_drivers_dir:
|
||||
sysfs_remove_link(mk->drivers_dir, driver_name);
|
||||
|
||||
out_free_driver_name:
|
||||
kfree(driver_name);
|
||||
|
||||
out_remove_kobj:
|
||||
sysfs_remove_link(&drv->p->kobj, "module");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -1474,7 +1474,7 @@ static const struct dev_pm_ops platform_dev_pm_ops = {
|
||||
USE_PLATFORM_PM_SLEEP_OPS
|
||||
};
|
||||
|
||||
struct bus_type platform_bus_type = {
|
||||
const struct bus_type platform_bus_type = {
|
||||
.name = "platform",
|
||||
.dev_groups = platform_dev_groups,
|
||||
.match = platform_match,
|
||||
|
||||
@@ -2259,14 +2259,12 @@ static const struct file_operations mtip_regs_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = simple_open,
|
||||
.read = mtip_hw_read_registers,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static const struct file_operations mtip_flags_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = simple_open,
|
||||
.read = mtip_hw_read_flags,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static void mtip_hw_debugfs_init(struct driver_data *dd)
|
||||
|
||||
@@ -2835,7 +2835,6 @@ static const struct file_operations pkt_ctl_fops = {
|
||||
.compat_ioctl = pkt_ctl_compat_ioctl,
|
||||
#endif
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static struct miscdevice pkt_misc = {
|
||||
|
||||
@@ -1983,7 +1983,6 @@ static const struct file_operations ublk_ch_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = ublk_ch_open,
|
||||
.release = ublk_ch_release,
|
||||
.llseek = no_llseek,
|
||||
.read_iter = ublk_ch_read_iter,
|
||||
.write_iter = ublk_ch_write_iter,
|
||||
.uring_cmd = ublk_ch_uring_cmd,
|
||||
|
||||
@@ -679,7 +679,6 @@ static const struct file_operations vhci_fops = {
|
||||
.poll = vhci_poll,
|
||||
.open = vhci_open,
|
||||
.release = vhci_release,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static struct miscdevice vhci_miscdev = {
|
||||
|
||||
@@ -309,7 +309,7 @@ static struct attribute *fsl_mc_bus_attrs[] = {
|
||||
|
||||
ATTRIBUTE_GROUPS(fsl_mc_bus);
|
||||
|
||||
struct bus_type fsl_mc_bus_type = {
|
||||
const struct bus_type fsl_mc_bus_type = {
|
||||
.name = "fsl-mc",
|
||||
.match = fsl_mc_bus_match,
|
||||
.uevent = fsl_mc_bus_uevent,
|
||||
|
||||
@@ -484,7 +484,6 @@ static const struct file_operations input_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = moxtet_debug_open,
|
||||
.read = input_read,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static ssize_t output_read(struct file *file, char __user *buf, size_t len,
|
||||
@@ -549,7 +548,6 @@ static const struct file_operations output_fops = {
|
||||
.open = moxtet_debug_open,
|
||||
.read = output_read,
|
||||
.write = output_write,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static int moxtet_register_debugfs(struct moxtet *moxtet)
|
||||
|
||||
@@ -111,7 +111,6 @@ static irqreturn_t ac_interrupt(int, void *);
|
||||
|
||||
static const struct file_operations ac_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.read = ac_read,
|
||||
.write = ac_write,
|
||||
.unlocked_ioctl = ac_ioctl,
|
||||
|
||||
@@ -353,7 +353,6 @@ static const struct file_operations ds1620_fops = {
|
||||
.open = ds1620_open,
|
||||
.read = ds1620_read,
|
||||
.unlocked_ioctl = ds1620_unlocked_ioctl,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static struct miscdevice ds1620_miscdev = {
|
||||
|
||||
@@ -107,7 +107,6 @@ static const struct file_operations dtlk_fops =
|
||||
.unlocked_ioctl = dtlk_ioctl,
|
||||
.open = dtlk_open,
|
||||
.release = dtlk_release,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
/* local prototypes */
|
||||
|
||||
@@ -700,7 +700,6 @@ hpet_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
|
||||
static const struct file_operations hpet_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.read = hpet_read,
|
||||
.poll = hpet_poll,
|
||||
.unlocked_ioctl = hpet_ioctl,
|
||||
|
||||
@@ -903,7 +903,6 @@ static const struct file_operations ipmi_wdog_fops = {
|
||||
.open = ipmi_open,
|
||||
.release = ipmi_close,
|
||||
.fasync = ipmi_fasync,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static struct miscdevice ipmi_wdog_miscdev = {
|
||||
|
||||
@@ -235,7 +235,6 @@ static const struct file_operations pc8736x_gpio_fileops = {
|
||||
.open = pc8736x_gpio_open,
|
||||
.write = nsc_gpio_write,
|
||||
.read = nsc_gpio_read,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static void __init pc8736x_init_shadow(void)
|
||||
|
||||
@@ -786,7 +786,6 @@ static const struct class ppdev_class = {
|
||||
|
||||
static const struct file_operations pp_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.read = pp_read,
|
||||
.write = pp_write,
|
||||
.poll = pp_poll,
|
||||
|
||||
@@ -68,7 +68,6 @@ static const struct file_operations scx200_gpio_fileops = {
|
||||
.read = nsc_gpio_read,
|
||||
.open = scx200_gpio_open,
|
||||
.release = scx200_gpio_release,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static struct cdev scx200_gpio_cdev; /* use 1 cdev for all pins */
|
||||
|
||||
@@ -1054,7 +1054,6 @@ static const struct file_operations sonypi_misc_fops = {
|
||||
.release = sonypi_misc_release,
|
||||
.fasync = sonypi_misc_fasync,
|
||||
.unlocked_ioctl = sonypi_misc_ioctl,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static struct miscdevice sonypi_misc_device = {
|
||||
|
||||
@@ -59,7 +59,6 @@ static int tpm_release(struct inode *inode, struct file *file)
|
||||
|
||||
const struct file_operations tpm_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.open = tpm_open,
|
||||
.read = tpm_common_read,
|
||||
.write = tpm_common_write,
|
||||
|
||||
@@ -243,7 +243,6 @@ static int vtpm_proxy_fops_release(struct inode *inode, struct file *filp)
|
||||
|
||||
static const struct file_operations vtpm_proxy_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.read = vtpm_proxy_fops_read,
|
||||
.write = vtpm_proxy_fops_write,
|
||||
.poll = vtpm_proxy_fops_poll,
|
||||
|
||||
@@ -46,7 +46,6 @@ static int tpmrm_release(struct inode *inode, struct file *file)
|
||||
|
||||
const struct file_operations tpmrm_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.open = tpmrm_open,
|
||||
.read = tpm_common_read,
|
||||
.write = tpm_common_write,
|
||||
|
||||
@@ -1093,7 +1093,6 @@ static const struct file_operations port_fops = {
|
||||
.poll = port_fops_poll,
|
||||
.release = port_fops_release,
|
||||
.fasync = port_fops_fasync,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -218,6 +218,14 @@ config COMMON_CLK_EN7523
|
||||
This driver provides the fixed clocks and gates present on Airoha
|
||||
ARM silicon.
|
||||
|
||||
config COMMON_CLK_EP93XX
|
||||
tristate "Clock driver for Cirrus Logic ep93xx SoC"
|
||||
depends on ARCH_EP93XX || COMPILE_TEST
|
||||
select AUXILIARY_BUS
|
||||
select REGMAP_MMIO
|
||||
help
|
||||
This driver supports the SoC clocks on the Cirrus Logic ep93xx.
|
||||
|
||||
config COMMON_CLK_FSL_FLEXSPI
|
||||
tristate "Clock driver for FlexSPI on Layerscape SoCs"
|
||||
depends on ARCH_LAYERSCAPE || COMPILE_TEST
|
||||
|
||||
@@ -37,6 +37,7 @@ obj-$(CONFIG_COMMON_CLK_CDCE706) += clk-cdce706.o
|
||||
obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o
|
||||
obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o
|
||||
obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o
|
||||
obj-$(CONFIG_COMMON_CLK_EP93XX) += clk-ep93xx.o
|
||||
obj-$(CONFIG_ARCH_SPARX5) += clk-sparx5.o
|
||||
obj-$(CONFIG_COMMON_CLK_EN7523) += clk-en7523.o
|
||||
obj-$(CONFIG_COMMON_CLK_FIXED_MMIO) += clk-fixed-mmio.o
|
||||
|
||||
@@ -0,0 +1,850 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Clock control for Cirrus EP93xx chips.
|
||||
* Copyright (C) 2021 Nikita Shubin <nikita.shubin@maquefel.me>
|
||||
*
|
||||
* Based on a rewrite of arch/arm/mach-ep93xx/clock.c:
|
||||
* Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
|
||||
*/
|
||||
#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <linux/soc/cirrus/ep93xx.h>
|
||||
#include <dt-bindings/clock/cirrus,ep9301-syscon.h>
|
||||
|
||||
#include <asm/div64.h>
|
||||
|
||||
#define EP93XX_EXT_CLK_RATE 14745600
|
||||
#define EP93XX_EXT_RTC_RATE 32768
|
||||
|
||||
#define EP93XX_SYSCON_POWER_STATE 0x00
|
||||
#define EP93XX_SYSCON_PWRCNT 0x04
|
||||
#define EP93XX_SYSCON_PWRCNT_UARTBAUD BIT(29)
|
||||
#define EP93XX_SYSCON_PWRCNT_USH_EN 28
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2M1 27
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2M0 26
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P8 25
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P9 24
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P6 23
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P7 22
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P4 21
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P5 20
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P2 19
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P3 18
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P0 17
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P1 16
|
||||
#define EP93XX_SYSCON_CLKSET1 0x20
|
||||
#define EP93XX_SYSCON_CLKSET1_NBYP1 BIT(23)
|
||||
#define EP93XX_SYSCON_CLKSET2 0x24
|
||||
#define EP93XX_SYSCON_CLKSET2_NBYP2 BIT(19)
|
||||
#define EP93XX_SYSCON_CLKSET2_PLL2_EN BIT(18)
|
||||
#define EP93XX_SYSCON_DEVCFG 0x80
|
||||
#define EP93XX_SYSCON_DEVCFG_U3EN 24
|
||||
#define EP93XX_SYSCON_DEVCFG_U2EN 20
|
||||
#define EP93XX_SYSCON_DEVCFG_U1EN 18
|
||||
#define EP93XX_SYSCON_VIDCLKDIV 0x84
|
||||
#define EP93XX_SYSCON_CLKDIV_ENABLE 15
|
||||
#define EP93XX_SYSCON_CLKDIV_ESEL BIT(14)
|
||||
#define EP93XX_SYSCON_CLKDIV_PSEL BIT(13)
|
||||
#define EP93XX_SYSCON_CLKDIV_MASK GENMASK(14, 13)
|
||||
#define EP93XX_SYSCON_CLKDIV_PDIV_SHIFT 8
|
||||
#define EP93XX_SYSCON_I2SCLKDIV 0x8c
|
||||
#define EP93XX_SYSCON_I2SCLKDIV_SENA 31
|
||||
#define EP93XX_SYSCON_I2SCLKDIV_ORIDE BIT(29)
|
||||
#define EP93XX_SYSCON_I2SCLKDIV_SPOL BIT(19)
|
||||
#define EP93XX_SYSCON_KEYTCHCLKDIV 0x90
|
||||
#define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN 31
|
||||
#define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV 16
|
||||
#define EP93XX_SYSCON_KEYTCHCLKDIV_KEN 15
|
||||
#define EP93XX_SYSCON_KEYTCHCLKDIV_KDIV 0
|
||||
#define EP93XX_SYSCON_CHIPID 0x94
|
||||
#define EP93XX_SYSCON_CHIPID_ID 0x9213
|
||||
|
||||
#define EP93XX_FIXED_CLK_COUNT 21
|
||||
|
||||
static const char ep93xx_adc_divisors[] = { 16, 4 };
|
||||
static const char ep93xx_sclk_divisors[] = { 2, 4 };
|
||||
static const char ep93xx_lrclk_divisors[] = { 32, 64, 128 };
|
||||
|
||||
struct ep93xx_clk {
|
||||
struct clk_hw hw;
|
||||
u16 idx;
|
||||
u16 reg;
|
||||
u32 mask;
|
||||
u8 bit_idx;
|
||||
u8 shift;
|
||||
u8 width;
|
||||
u8 num_div;
|
||||
const char *div;
|
||||
};
|
||||
|
||||
struct ep93xx_clk_priv {
|
||||
spinlock_t lock;
|
||||
struct ep93xx_regmap_adev *aux_dev;
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
struct regmap *map;
|
||||
struct clk_hw *fixed[EP93XX_FIXED_CLK_COUNT];
|
||||
struct ep93xx_clk reg[];
|
||||
};
|
||||
|
||||
static struct ep93xx_clk *ep93xx_clk_from(struct clk_hw *hw)
|
||||
{
|
||||
return container_of(hw, struct ep93xx_clk, hw);
|
||||
}
|
||||
|
||||
static struct ep93xx_clk_priv *ep93xx_priv_from(struct ep93xx_clk *clk)
|
||||
{
|
||||
return container_of(clk, struct ep93xx_clk_priv, reg[clk->idx]);
|
||||
}
|
||||
|
||||
static void ep93xx_clk_write(struct ep93xx_clk_priv *priv, unsigned int reg, unsigned int val)
|
||||
{
|
||||
struct ep93xx_regmap_adev *aux = priv->aux_dev;
|
||||
|
||||
aux->write(aux->map, aux->lock, reg, val);
|
||||
}
|
||||
|
||||
static int ep93xx_clk_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct ep93xx_clk *clk = ep93xx_clk_from(hw);
|
||||
struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
|
||||
u32 val;
|
||||
|
||||
regmap_read(priv->map, clk->reg, &val);
|
||||
|
||||
return !!(val & BIT(clk->bit_idx));
|
||||
}
|
||||
|
||||
static int ep93xx_clk_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct ep93xx_clk *clk = ep93xx_clk_from(hw);
|
||||
struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
|
||||
u32 val;
|
||||
|
||||
guard(spinlock_irqsave)(&priv->lock);
|
||||
|
||||
regmap_read(priv->map, clk->reg, &val);
|
||||
val |= BIT(clk->bit_idx);
|
||||
|
||||
ep93xx_clk_write(priv, clk->reg, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ep93xx_clk_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct ep93xx_clk *clk = ep93xx_clk_from(hw);
|
||||
struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
|
||||
u32 val;
|
||||
|
||||
guard(spinlock_irqsave)(&priv->lock);
|
||||
|
||||
regmap_read(priv->map, clk->reg, &val);
|
||||
val &= ~BIT(clk->bit_idx);
|
||||
|
||||
ep93xx_clk_write(priv, clk->reg, val);
|
||||
}
|
||||
|
||||
static const struct clk_ops clk_ep93xx_gate_ops = {
|
||||
.enable = ep93xx_clk_enable,
|
||||
.disable = ep93xx_clk_disable,
|
||||
.is_enabled = ep93xx_clk_is_enabled,
|
||||
};
|
||||
|
||||
static int ep93xx_clk_register_gate(struct ep93xx_clk *clk,
|
||||
const char *name,
|
||||
struct clk_parent_data *parent_data,
|
||||
unsigned long flags,
|
||||
unsigned int reg,
|
||||
u8 bit_idx)
|
||||
{
|
||||
struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
|
||||
struct clk_init_data init = { };
|
||||
|
||||
init.name = name;
|
||||
init.ops = &clk_ep93xx_gate_ops;
|
||||
init.flags = flags;
|
||||
init.parent_data = parent_data;
|
||||
init.num_parents = 1;
|
||||
|
||||
clk->reg = reg;
|
||||
clk->bit_idx = bit_idx;
|
||||
clk->hw.init = &init;
|
||||
|
||||
return devm_clk_hw_register(priv->dev, &clk->hw);
|
||||
}
|
||||
|
||||
static u8 ep93xx_mux_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct ep93xx_clk *clk = ep93xx_clk_from(hw);
|
||||
struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
|
||||
u32 val;
|
||||
|
||||
regmap_read(priv->map, clk->reg, &val);
|
||||
|
||||
val &= EP93XX_SYSCON_CLKDIV_MASK;
|
||||
|
||||
switch (val) {
|
||||
case EP93XX_SYSCON_CLKDIV_ESEL:
|
||||
return 1; /* PLL1 */
|
||||
case EP93XX_SYSCON_CLKDIV_MASK:
|
||||
return 2; /* PLL2 */
|
||||
default:
|
||||
return 0; /* XTALI */
|
||||
};
|
||||
}
|
||||
|
||||
static int ep93xx_mux_set_parent_lock(struct clk_hw *hw, u8 index)
|
||||
{
|
||||
struct ep93xx_clk *clk = ep93xx_clk_from(hw);
|
||||
struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
|
||||
u32 val;
|
||||
|
||||
if (index >= 3)
|
||||
return -EINVAL;
|
||||
|
||||
guard(spinlock_irqsave)(&priv->lock);
|
||||
|
||||
regmap_read(priv->map, clk->reg, &val);
|
||||
val &= ~(EP93XX_SYSCON_CLKDIV_MASK);
|
||||
val |= index > 0 ? EP93XX_SYSCON_CLKDIV_ESEL : 0;
|
||||
val |= index > 1 ? EP93XX_SYSCON_CLKDIV_PSEL : 0;
|
||||
|
||||
ep93xx_clk_write(priv, clk->reg, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool is_best(unsigned long rate, unsigned long now,
|
||||
unsigned long best)
|
||||
{
|
||||
return abs_diff(rate, now) < abs_diff(rate, best);
|
||||
}
|
||||
|
||||
static int ep93xx_mux_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
unsigned long best_rate = 0, actual_rate, mclk_rate;
|
||||
unsigned long rate = req->rate;
|
||||
struct clk_hw *parent_best = NULL;
|
||||
unsigned long parent_rate_best;
|
||||
unsigned long parent_rate;
|
||||
int div, pdiv;
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
* Try the two pll's and the external clock,
|
||||
* because the valid predividers are 2, 2.5 and 3, we multiply
|
||||
* all the clocks by 2 to avoid floating point math.
|
||||
*
|
||||
* This is based on the algorithm in the ep93xx raster guide:
|
||||
* http://be-a-maverick.com/en/pubs/appNote/AN269REV1.pdf
|
||||
*
|
||||
*/
|
||||
for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
|
||||
struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i);
|
||||
|
||||
parent_rate = clk_hw_get_rate(parent);
|
||||
mclk_rate = parent_rate * 2;
|
||||
|
||||
/* Try each predivider value */
|
||||
for (pdiv = 4; pdiv <= 6; pdiv++) {
|
||||
div = DIV_ROUND_CLOSEST(mclk_rate, rate * pdiv);
|
||||
if (!in_range(div, 1, 127))
|
||||
continue;
|
||||
|
||||
actual_rate = DIV_ROUND_CLOSEST(mclk_rate, pdiv * div);
|
||||
if (is_best(rate, actual_rate, best_rate)) {
|
||||
best_rate = actual_rate;
|
||||
parent_rate_best = parent_rate;
|
||||
parent_best = parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!parent_best)
|
||||
return -EINVAL;
|
||||
|
||||
req->best_parent_rate = parent_rate_best;
|
||||
req->best_parent_hw = parent_best;
|
||||
req->rate = best_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long ep93xx_ddiv_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct ep93xx_clk *clk = ep93xx_clk_from(hw);
|
||||
struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
|
||||
unsigned int pdiv, div;
|
||||
u32 val;
|
||||
|
||||
regmap_read(priv->map, clk->reg, &val);
|
||||
pdiv = (val >> EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) & GENMASK(1, 0);
|
||||
div = val & GENMASK(6, 0);
|
||||
if (!div)
|
||||
return 0;
|
||||
|
||||
return DIV_ROUND_CLOSEST(parent_rate * 2, (pdiv + 3) * div);
|
||||
}
|
||||
|
||||
static int ep93xx_ddiv_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct ep93xx_clk *clk = ep93xx_clk_from(hw);
|
||||
struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
|
||||
int pdiv, div, npdiv, ndiv;
|
||||
unsigned long actual_rate, mclk_rate, rate_err = ULONG_MAX;
|
||||
u32 val;
|
||||
|
||||
regmap_read(priv->map, clk->reg, &val);
|
||||
mclk_rate = parent_rate * 2;
|
||||
|
||||
for (pdiv = 4; pdiv <= 6; pdiv++) {
|
||||
div = DIV_ROUND_CLOSEST(mclk_rate, rate * pdiv);
|
||||
if (!in_range(div, 1, 127))
|
||||
continue;
|
||||
|
||||
actual_rate = DIV_ROUND_CLOSEST(mclk_rate, pdiv * div);
|
||||
if (abs(actual_rate - rate) < rate_err) {
|
||||
npdiv = pdiv - 3;
|
||||
ndiv = div;
|
||||
rate_err = abs(actual_rate - rate);
|
||||
}
|
||||
}
|
||||
|
||||
if (rate_err == ULONG_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Clear old dividers.
|
||||
* Bit 7 is reserved bit in all ClkDiv registers.
|
||||
*/
|
||||
val &= ~(GENMASK(9, 0) & ~BIT(7));
|
||||
|
||||
/* Set the new pdiv and div bits for the new clock rate */
|
||||
val |= (npdiv << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | ndiv;
|
||||
|
||||
ep93xx_clk_write(priv, clk->reg, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops clk_ddiv_ops = {
|
||||
.enable = ep93xx_clk_enable,
|
||||
.disable = ep93xx_clk_disable,
|
||||
.is_enabled = ep93xx_clk_is_enabled,
|
||||
.get_parent = ep93xx_mux_get_parent,
|
||||
.set_parent = ep93xx_mux_set_parent_lock,
|
||||
.determine_rate = ep93xx_mux_determine_rate,
|
||||
.recalc_rate = ep93xx_ddiv_recalc_rate,
|
||||
.set_rate = ep93xx_ddiv_set_rate,
|
||||
};
|
||||
|
||||
static int ep93xx_clk_register_ddiv(struct ep93xx_clk *clk,
|
||||
const char *name,
|
||||
struct clk_parent_data *parent_data,
|
||||
u8 num_parents,
|
||||
unsigned int reg,
|
||||
u8 bit_idx)
|
||||
{
|
||||
struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
|
||||
struct clk_init_data init = { };
|
||||
|
||||
init.name = name;
|
||||
init.ops = &clk_ddiv_ops;
|
||||
init.flags = 0;
|
||||
init.parent_data = parent_data;
|
||||
init.num_parents = num_parents;
|
||||
|
||||
clk->reg = reg;
|
||||
clk->bit_idx = bit_idx;
|
||||
clk->hw.init = &init;
|
||||
|
||||
return devm_clk_hw_register(priv->dev, &clk->hw);
|
||||
}
|
||||
|
||||
static unsigned long ep93xx_div_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct ep93xx_clk *clk = ep93xx_clk_from(hw);
|
||||
struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
|
||||
u32 val;
|
||||
u8 index;
|
||||
|
||||
regmap_read(priv->map, clk->reg, &val);
|
||||
index = (val & clk->mask) >> clk->shift;
|
||||
if (index >= clk->num_div)
|
||||
return 0;
|
||||
|
||||
return DIV_ROUND_CLOSEST(parent_rate, clk->div[index]);
|
||||
}
|
||||
|
||||
static long ep93xx_div_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
struct ep93xx_clk *clk = ep93xx_clk_from(hw);
|
||||
unsigned long best = 0, now;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < clk->num_div; i++) {
|
||||
if ((rate * clk->div[i]) == *parent_rate)
|
||||
return rate;
|
||||
|
||||
now = DIV_ROUND_CLOSEST(*parent_rate, clk->div[i]);
|
||||
if (!best || is_best(rate, now, best))
|
||||
best = now;
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
static int ep93xx_div_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct ep93xx_clk *clk = ep93xx_clk_from(hw);
|
||||
struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
|
||||
unsigned int i;
|
||||
u32 val;
|
||||
|
||||
regmap_read(priv->map, clk->reg, &val);
|
||||
val &= ~clk->mask;
|
||||
for (i = 0; i < clk->num_div; i++)
|
||||
if (rate == DIV_ROUND_CLOSEST(parent_rate, clk->div[i]))
|
||||
break;
|
||||
|
||||
if (i == clk->num_div)
|
||||
return -EINVAL;
|
||||
|
||||
val |= i << clk->shift;
|
||||
|
||||
ep93xx_clk_write(priv, clk->reg, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops ep93xx_div_ops = {
|
||||
.enable = ep93xx_clk_enable,
|
||||
.disable = ep93xx_clk_disable,
|
||||
.is_enabled = ep93xx_clk_is_enabled,
|
||||
.recalc_rate = ep93xx_div_recalc_rate,
|
||||
.round_rate = ep93xx_div_round_rate,
|
||||
.set_rate = ep93xx_div_set_rate,
|
||||
};
|
||||
|
||||
static int ep93xx_register_div(struct ep93xx_clk *clk,
|
||||
const char *name,
|
||||
const struct clk_parent_data *parent_data,
|
||||
unsigned int reg,
|
||||
u8 enable_bit,
|
||||
u8 shift,
|
||||
u8 width,
|
||||
const char *clk_divisors,
|
||||
u8 num_div)
|
||||
{
|
||||
struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
|
||||
struct clk_init_data init = { };
|
||||
|
||||
init.name = name;
|
||||
init.ops = &ep93xx_div_ops;
|
||||
init.flags = 0;
|
||||
init.parent_data = parent_data;
|
||||
init.num_parents = 1;
|
||||
|
||||
clk->reg = reg;
|
||||
clk->bit_idx = enable_bit;
|
||||
clk->mask = GENMASK(shift + width - 1, shift);
|
||||
clk->shift = shift;
|
||||
clk->div = clk_divisors;
|
||||
clk->num_div = num_div;
|
||||
clk->hw.init = &init;
|
||||
|
||||
return devm_clk_hw_register(priv->dev, &clk->hw);
|
||||
}
|
||||
|
||||
struct ep93xx_gate {
|
||||
unsigned int idx;
|
||||
unsigned int bit;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static const struct ep93xx_gate ep93xx_uarts[] = {
|
||||
{ EP93XX_CLK_UART1, EP93XX_SYSCON_DEVCFG_U1EN, "uart1" },
|
||||
{ EP93XX_CLK_UART2, EP93XX_SYSCON_DEVCFG_U2EN, "uart2" },
|
||||
{ EP93XX_CLK_UART3, EP93XX_SYSCON_DEVCFG_U3EN, "uart3" },
|
||||
};
|
||||
|
||||
static int ep93xx_uart_clock_init(struct ep93xx_clk_priv *priv)
|
||||
{
|
||||
struct clk_parent_data parent_data = { };
|
||||
unsigned int i, idx, ret, clk_uart_div;
|
||||
struct ep93xx_clk *clk;
|
||||
u32 val;
|
||||
|
||||
regmap_read(priv->map, EP93XX_SYSCON_PWRCNT, &val);
|
||||
if (val & EP93XX_SYSCON_PWRCNT_UARTBAUD)
|
||||
clk_uart_div = 1;
|
||||
else
|
||||
clk_uart_div = 2;
|
||||
|
||||
priv->fixed[EP93XX_CLK_UART] =
|
||||
devm_clk_hw_register_fixed_factor_index(priv->dev, "uart",
|
||||
0, /* XTALI external clock */
|
||||
0, 1, clk_uart_div);
|
||||
parent_data.hw = priv->fixed[EP93XX_CLK_UART];
|
||||
|
||||
/* parenting uart gate clocks to uart clock */
|
||||
for (i = 0; i < ARRAY_SIZE(ep93xx_uarts); i++) {
|
||||
idx = ep93xx_uarts[i].idx - EP93XX_CLK_UART1;
|
||||
clk = &priv->reg[idx];
|
||||
clk->idx = idx;
|
||||
ret = ep93xx_clk_register_gate(clk,
|
||||
ep93xx_uarts[i].name,
|
||||
&parent_data, CLK_SET_RATE_PARENT,
|
||||
EP93XX_SYSCON_DEVCFG,
|
||||
ep93xx_uarts[i].bit);
|
||||
if (ret)
|
||||
return dev_err_probe(priv->dev, ret,
|
||||
"failed to register uart[%d] clock\n", i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ep93xx_gate ep93xx_dmas[] = {
|
||||
{ EP93XX_CLK_M2M0, EP93XX_SYSCON_PWRCNT_DMA_M2M0, "m2m0" },
|
||||
{ EP93XX_CLK_M2M1, EP93XX_SYSCON_PWRCNT_DMA_M2M1, "m2m1" },
|
||||
{ EP93XX_CLK_M2P0, EP93XX_SYSCON_PWRCNT_DMA_M2P0, "m2p0" },
|
||||
{ EP93XX_CLK_M2P1, EP93XX_SYSCON_PWRCNT_DMA_M2P1, "m2p1" },
|
||||
{ EP93XX_CLK_M2P2, EP93XX_SYSCON_PWRCNT_DMA_M2P2, "m2p2" },
|
||||
{ EP93XX_CLK_M2P3, EP93XX_SYSCON_PWRCNT_DMA_M2P3, "m2p3" },
|
||||
{ EP93XX_CLK_M2P4, EP93XX_SYSCON_PWRCNT_DMA_M2P4, "m2p4" },
|
||||
{ EP93XX_CLK_M2P5, EP93XX_SYSCON_PWRCNT_DMA_M2P5, "m2p5" },
|
||||
{ EP93XX_CLK_M2P6, EP93XX_SYSCON_PWRCNT_DMA_M2P6, "m2p6" },
|
||||
{ EP93XX_CLK_M2P7, EP93XX_SYSCON_PWRCNT_DMA_M2P7, "m2p7" },
|
||||
{ EP93XX_CLK_M2P8, EP93XX_SYSCON_PWRCNT_DMA_M2P8, "m2p8" },
|
||||
{ EP93XX_CLK_M2P9, EP93XX_SYSCON_PWRCNT_DMA_M2P9, "m2p9" },
|
||||
};
|
||||
|
||||
static int ep93xx_dma_clock_init(struct ep93xx_clk_priv *priv)
|
||||
{
|
||||
struct clk_parent_data parent_data = { };
|
||||
unsigned int i, idx;
|
||||
|
||||
parent_data.hw = priv->fixed[EP93XX_CLK_HCLK];
|
||||
for (i = 0; i < ARRAY_SIZE(ep93xx_dmas); i++) {
|
||||
idx = ep93xx_dmas[i].idx;
|
||||
priv->fixed[idx] = devm_clk_hw_register_gate_parent_data(priv->dev,
|
||||
ep93xx_dmas[i].name,
|
||||
&parent_data, 0,
|
||||
priv->base + EP93XX_SYSCON_PWRCNT,
|
||||
ep93xx_dmas[i].bit,
|
||||
0,
|
||||
&priv->lock);
|
||||
if (IS_ERR(priv->fixed[idx]))
|
||||
return PTR_ERR(priv->fixed[idx]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clk_hw *of_clk_ep93xx_get(struct of_phandle_args *clkspec, void *data)
|
||||
{
|
||||
struct ep93xx_clk_priv *priv = data;
|
||||
unsigned int idx = clkspec->args[0];
|
||||
|
||||
if (idx < EP93XX_CLK_UART1)
|
||||
return priv->fixed[idx];
|
||||
|
||||
if (idx <= EP93XX_CLK_I2S_LRCLK)
|
||||
return &priv->reg[idx - EP93XX_CLK_UART1].hw;
|
||||
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS
|
||||
*/
|
||||
static unsigned long calc_pll_rate(u64 rate, u32 config_word)
|
||||
{
|
||||
rate *= ((config_word >> 11) & GENMASK(4, 0)) + 1; /* X1FBD */
|
||||
rate *= ((config_word >> 5) & GENMASK(5, 0)) + 1; /* X2FBD */
|
||||
do_div(rate, (config_word & GENMASK(4, 0)) + 1); /* X2IPD */
|
||||
rate >>= (config_word >> 16) & GENMASK(1, 0); /* PS */
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static int ep93xx_plls_init(struct ep93xx_clk_priv *priv)
|
||||
{
|
||||
const char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
|
||||
const char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
|
||||
const char pclk_divisors[] = { 1, 2, 4, 8 };
|
||||
struct clk_parent_data xtali = { .index = 0 };
|
||||
unsigned int clk_f_div, clk_h_div, clk_p_div;
|
||||
unsigned long clk_pll1_rate, clk_pll2_rate;
|
||||
struct device *dev = priv->dev;
|
||||
struct clk_hw *hw, *pll1;
|
||||
u32 value;
|
||||
|
||||
/* Determine the bootloader configured pll1 rate */
|
||||
regmap_read(priv->map, EP93XX_SYSCON_CLKSET1, &value);
|
||||
|
||||
if (value & EP93XX_SYSCON_CLKSET1_NBYP1)
|
||||
clk_pll1_rate = calc_pll_rate(EP93XX_EXT_CLK_RATE, value);
|
||||
else
|
||||
clk_pll1_rate = EP93XX_EXT_CLK_RATE;
|
||||
|
||||
pll1 = devm_clk_hw_register_fixed_rate_parent_data(dev, "pll1", &xtali,
|
||||
0, clk_pll1_rate);
|
||||
if (IS_ERR(pll1))
|
||||
return PTR_ERR(pll1);
|
||||
|
||||
priv->fixed[EP93XX_CLK_PLL1] = pll1;
|
||||
|
||||
/* Initialize the pll1 derived clocks */
|
||||
clk_f_div = fclk_divisors[(value >> 25) & GENMASK(2, 0)];
|
||||
clk_h_div = hclk_divisors[(value >> 20) & GENMASK(2, 0)];
|
||||
clk_p_div = pclk_divisors[(value >> 18) & GENMASK(1, 0)];
|
||||
|
||||
hw = devm_clk_hw_register_fixed_factor_parent_hw(dev, "fclk", pll1, 0, 1, clk_f_div);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
|
||||
priv->fixed[EP93XX_CLK_FCLK] = hw;
|
||||
|
||||
hw = devm_clk_hw_register_fixed_factor_parent_hw(dev, "hclk", pll1, 0, 1, clk_h_div);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
|
||||
priv->fixed[EP93XX_CLK_HCLK] = hw;
|
||||
|
||||
hw = devm_clk_hw_register_fixed_factor_parent_hw(dev, "pclk", hw, 0, 1, clk_p_div);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
|
||||
priv->fixed[EP93XX_CLK_PCLK] = hw;
|
||||
|
||||
/* Determine the bootloader configured pll2 rate */
|
||||
regmap_read(priv->map, EP93XX_SYSCON_CLKSET2, &value);
|
||||
if (!(value & EP93XX_SYSCON_CLKSET2_NBYP2))
|
||||
clk_pll2_rate = EP93XX_EXT_CLK_RATE;
|
||||
else if (value & EP93XX_SYSCON_CLKSET2_PLL2_EN)
|
||||
clk_pll2_rate = calc_pll_rate(EP93XX_EXT_CLK_RATE, value);
|
||||
else
|
||||
clk_pll2_rate = 0;
|
||||
|
||||
hw = devm_clk_hw_register_fixed_rate_parent_data(dev, "pll2", &xtali,
|
||||
0, clk_pll2_rate);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
|
||||
priv->fixed[EP93XX_CLK_PLL2] = hw;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ep93xx_clk_probe(struct auxiliary_device *adev,
|
||||
const struct auxiliary_device_id *id)
|
||||
{
|
||||
struct ep93xx_regmap_adev *rdev = to_ep93xx_regmap_adev(adev);
|
||||
struct clk_parent_data xtali = { .index = 0 };
|
||||
struct clk_parent_data ddiv_pdata[3] = { };
|
||||
unsigned int clk_spi_div, clk_usb_div;
|
||||
struct clk_parent_data pdata = {};
|
||||
struct device *dev = &adev->dev;
|
||||
struct ep93xx_clk_priv *priv;
|
||||
struct ep93xx_clk *clk;
|
||||
struct clk_hw *hw;
|
||||
unsigned int idx;
|
||||
int ret;
|
||||
u32 value;
|
||||
|
||||
priv = devm_kzalloc(dev, struct_size(priv, reg, 10), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&priv->lock);
|
||||
priv->dev = dev;
|
||||
priv->aux_dev = rdev;
|
||||
priv->map = rdev->map;
|
||||
priv->base = rdev->base;
|
||||
|
||||
ret = ep93xx_plls_init(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
regmap_read(priv->map, EP93XX_SYSCON_CLKSET2, &value);
|
||||
clk_usb_div = (value >> 28 & GENMASK(3, 0)) + 1;
|
||||
hw = devm_clk_hw_register_fixed_factor_parent_hw(dev, "usb_clk",
|
||||
priv->fixed[EP93XX_CLK_PLL2], 0, 1,
|
||||
clk_usb_div);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
|
||||
priv->fixed[EP93XX_CLK_USB] = hw;
|
||||
|
||||
ret = ep93xx_uart_clock_init(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ep93xx_dma_clock_init(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clk_spi_div = id->driver_data;
|
||||
hw = devm_clk_hw_register_fixed_factor_index(dev, "ep93xx-spi.0",
|
||||
0, /* XTALI external clock */
|
||||
0, 1, clk_spi_div);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
|
||||
priv->fixed[EP93XX_CLK_SPI] = hw;
|
||||
|
||||
/* PWM clock */
|
||||
hw = devm_clk_hw_register_fixed_factor_index(dev, "pwm_clk", 0, /* XTALI external clock */
|
||||
0, 1, 1);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
|
||||
priv->fixed[EP93XX_CLK_PWM] = hw;
|
||||
|
||||
/* USB clock */
|
||||
pdata.hw = priv->fixed[EP93XX_CLK_USB];
|
||||
hw = devm_clk_hw_register_gate_parent_data(priv->dev, "ohci-platform", &pdata,
|
||||
0, priv->base + EP93XX_SYSCON_PWRCNT,
|
||||
EP93XX_SYSCON_PWRCNT_USH_EN, 0,
|
||||
&priv->lock);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
|
||||
priv->fixed[EP93XX_CLK_USB] = hw;
|
||||
|
||||
ddiv_pdata[0].index = 0; /* XTALI external clock */
|
||||
ddiv_pdata[1].hw = priv->fixed[EP93XX_CLK_PLL1];
|
||||
ddiv_pdata[2].hw = priv->fixed[EP93XX_CLK_PLL2];
|
||||
|
||||
/* touchscreen/ADC clock */
|
||||
idx = EP93XX_CLK_ADC - EP93XX_CLK_UART1;
|
||||
clk = &priv->reg[idx];
|
||||
clk->idx = idx;
|
||||
ret = ep93xx_register_div(clk, "ep93xx-adc", &xtali,
|
||||
EP93XX_SYSCON_KEYTCHCLKDIV,
|
||||
EP93XX_SYSCON_KEYTCHCLKDIV_TSEN,
|
||||
EP93XX_SYSCON_KEYTCHCLKDIV_ADIV,
|
||||
1,
|
||||
ep93xx_adc_divisors,
|
||||
ARRAY_SIZE(ep93xx_adc_divisors));
|
||||
|
||||
|
||||
/* keypad clock */
|
||||
idx = EP93XX_CLK_KEYPAD - EP93XX_CLK_UART1;
|
||||
clk = &priv->reg[idx];
|
||||
clk->idx = idx;
|
||||
ret = ep93xx_register_div(clk, "ep93xx-keypad", &xtali,
|
||||
EP93XX_SYSCON_KEYTCHCLKDIV,
|
||||
EP93XX_SYSCON_KEYTCHCLKDIV_KEN,
|
||||
EP93XX_SYSCON_KEYTCHCLKDIV_KDIV,
|
||||
1,
|
||||
ep93xx_adc_divisors,
|
||||
ARRAY_SIZE(ep93xx_adc_divisors));
|
||||
|
||||
/*
|
||||
* On reset PDIV and VDIV is set to zero, while PDIV zero
|
||||
* means clock disable, VDIV shouldn't be zero.
|
||||
* So we set both video and i2s dividers to minimum.
|
||||
* ENA - Enable CLK divider.
|
||||
* PDIV - 00 - Disable clock
|
||||
* VDIV - at least 2
|
||||
*/
|
||||
|
||||
/* Check and enable video clk registers */
|
||||
regmap_read(priv->map, EP93XX_SYSCON_VIDCLKDIV, &value);
|
||||
value |= BIT(EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | 2;
|
||||
ep93xx_clk_write(priv, EP93XX_SYSCON_VIDCLKDIV, value);
|
||||
|
||||
/* Check and enable i2s clk registers */
|
||||
regmap_read(priv->map, EP93XX_SYSCON_I2SCLKDIV, &value);
|
||||
value |= BIT(EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | 2;
|
||||
|
||||
/*
|
||||
* Override the SAI_MSTR_CLK_CFG from the I2S block and use the
|
||||
* I2SClkDiv Register settings. LRCLK transitions on the falling SCLK
|
||||
* edge.
|
||||
*/
|
||||
value |= EP93XX_SYSCON_I2SCLKDIV_ORIDE | EP93XX_SYSCON_I2SCLKDIV_SPOL;
|
||||
ep93xx_clk_write(priv, EP93XX_SYSCON_I2SCLKDIV, value);
|
||||
|
||||
/* video clk */
|
||||
idx = EP93XX_CLK_VIDEO - EP93XX_CLK_UART1;
|
||||
clk = &priv->reg[idx];
|
||||
clk->idx = idx;
|
||||
ret = ep93xx_clk_register_ddiv(clk, "ep93xx-fb",
|
||||
ddiv_pdata, ARRAY_SIZE(ddiv_pdata),
|
||||
EP93XX_SYSCON_VIDCLKDIV,
|
||||
EP93XX_SYSCON_CLKDIV_ENABLE);
|
||||
|
||||
/* i2s clk */
|
||||
idx = EP93XX_CLK_I2S_MCLK - EP93XX_CLK_UART1;
|
||||
clk = &priv->reg[idx];
|
||||
clk->idx = idx;
|
||||
ret = ep93xx_clk_register_ddiv(clk, "mclk",
|
||||
ddiv_pdata, ARRAY_SIZE(ddiv_pdata),
|
||||
EP93XX_SYSCON_I2SCLKDIV,
|
||||
EP93XX_SYSCON_CLKDIV_ENABLE);
|
||||
|
||||
/* i2s sclk */
|
||||
idx = EP93XX_CLK_I2S_SCLK - EP93XX_CLK_UART1;
|
||||
clk = &priv->reg[idx];
|
||||
clk->idx = idx;
|
||||
pdata.hw = &priv->reg[EP93XX_CLK_I2S_MCLK - EP93XX_CLK_UART1].hw;
|
||||
ret = ep93xx_register_div(clk, "sclk", &pdata,
|
||||
EP93XX_SYSCON_I2SCLKDIV,
|
||||
EP93XX_SYSCON_I2SCLKDIV_SENA,
|
||||
16, /* EP93XX_I2SCLKDIV_SDIV_SHIFT */
|
||||
1, /* EP93XX_I2SCLKDIV_SDIV_WIDTH */
|
||||
ep93xx_sclk_divisors,
|
||||
ARRAY_SIZE(ep93xx_sclk_divisors));
|
||||
|
||||
/* i2s lrclk */
|
||||
idx = EP93XX_CLK_I2S_LRCLK - EP93XX_CLK_UART1;
|
||||
clk = &priv->reg[idx];
|
||||
clk->idx = idx;
|
||||
pdata.hw = &priv->reg[EP93XX_CLK_I2S_SCLK - EP93XX_CLK_UART1].hw;
|
||||
ret = ep93xx_register_div(clk, "lrclk", &pdata,
|
||||
EP93XX_SYSCON_I2SCLKDIV,
|
||||
EP93XX_SYSCON_I2SCLKDIV_SENA,
|
||||
17, /* EP93XX_I2SCLKDIV_LRDIV32_SHIFT */
|
||||
2, /* EP93XX_I2SCLKDIV_LRDIV32_WIDTH */
|
||||
ep93xx_lrclk_divisors,
|
||||
ARRAY_SIZE(ep93xx_lrclk_divisors));
|
||||
|
||||
/* IrDa clk uses same pattern but no init code presents in original clock driver */
|
||||
return devm_of_clk_add_hw_provider(priv->dev, of_clk_ep93xx_get, priv);
|
||||
}
|
||||
|
||||
static const struct auxiliary_device_id ep93xx_clk_ids[] = {
|
||||
{ .name = "soc_ep93xx.clk-ep93xx", .driver_data = 2, },
|
||||
{ .name = "soc_ep93xx.clk-ep93xx.e2", .driver_data = 1, },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(auxiliary, ep93xx_clk_ids);
|
||||
|
||||
static struct auxiliary_driver ep93xx_clk_driver = {
|
||||
.probe = ep93xx_clk_probe,
|
||||
.id_table = ep93xx_clk_ids,
|
||||
};
|
||||
module_auxiliary_driver(ep93xx_clk_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Nikita Shubin <nikita.shubin@maquefel.me>");
|
||||
MODULE_DESCRIPTION("Clock control for Cirrus EP93xx chips");
|
||||
@@ -454,7 +454,6 @@ out_unlock:
|
||||
|
||||
static const struct file_operations counter_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.read = counter_chrdev_read,
|
||||
.poll = counter_chrdev_poll,
|
||||
.unlocked_ioctl = counter_chrdev_ioctl,
|
||||
|
||||
+231
-56
@@ -17,14 +17,15 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/of_dma.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/platform_data/dma-ep93xx.h>
|
||||
|
||||
#include "dmaengine.h"
|
||||
|
||||
/* M2P registers */
|
||||
@@ -104,6 +105,31 @@
|
||||
#define DMA_MAX_CHAN_BYTES 0xffff
|
||||
#define DMA_MAX_CHAN_DESCRIPTORS 32
|
||||
|
||||
/*
|
||||
* M2P channels.
|
||||
*
|
||||
* Note that these values are also directly used for setting the PPALLOC
|
||||
* register.
|
||||
*/
|
||||
#define EP93XX_DMA_I2S1 0
|
||||
#define EP93XX_DMA_I2S2 1
|
||||
#define EP93XX_DMA_AAC1 2
|
||||
#define EP93XX_DMA_AAC2 3
|
||||
#define EP93XX_DMA_AAC3 4
|
||||
#define EP93XX_DMA_I2S3 5
|
||||
#define EP93XX_DMA_UART1 6
|
||||
#define EP93XX_DMA_UART2 7
|
||||
#define EP93XX_DMA_UART3 8
|
||||
#define EP93XX_DMA_IRDA 9
|
||||
/* M2M channels */
|
||||
#define EP93XX_DMA_SSP 10
|
||||
#define EP93XX_DMA_IDE 11
|
||||
|
||||
enum ep93xx_dma_type {
|
||||
M2P_DMA,
|
||||
M2M_DMA,
|
||||
};
|
||||
|
||||
struct ep93xx_dma_engine;
|
||||
static int ep93xx_dma_slave_config_write(struct dma_chan *chan,
|
||||
enum dma_transfer_direction dir,
|
||||
@@ -129,11 +155,17 @@ struct ep93xx_dma_desc {
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
struct ep93xx_dma_chan_cfg {
|
||||
u8 port;
|
||||
enum dma_transfer_direction dir;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ep93xx_dma_chan - an EP93xx DMA M2P/M2M channel
|
||||
* @chan: dmaengine API channel
|
||||
* @edma: pointer to the engine device
|
||||
* @regs: memory mapped registers
|
||||
* @dma_cfg: channel number, direction
|
||||
* @irq: interrupt number of the channel
|
||||
* @clk: clock used by this channel
|
||||
* @tasklet: channel specific tasklet used for callbacks
|
||||
@@ -157,14 +189,12 @@ struct ep93xx_dma_desc {
|
||||
* descriptor in the chain. When a descriptor is moved to the @active queue,
|
||||
* the first and chained descriptors are flattened into a single list.
|
||||
*
|
||||
* @chan.private holds pointer to &struct ep93xx_dma_data which contains
|
||||
* necessary channel configuration information. For memcpy channels this must
|
||||
* be %NULL.
|
||||
*/
|
||||
struct ep93xx_dma_chan {
|
||||
struct dma_chan chan;
|
||||
const struct ep93xx_dma_engine *edma;
|
||||
void __iomem *regs;
|
||||
struct ep93xx_dma_chan_cfg dma_cfg;
|
||||
int irq;
|
||||
struct clk *clk;
|
||||
struct tasklet_struct tasklet;
|
||||
@@ -216,6 +246,11 @@ struct ep93xx_dma_engine {
|
||||
struct ep93xx_dma_chan channels[] __counted_by(num_channels);
|
||||
};
|
||||
|
||||
struct ep93xx_edma_data {
|
||||
u32 id;
|
||||
size_t num_channels;
|
||||
};
|
||||
|
||||
static inline struct device *chan2dev(struct ep93xx_dma_chan *edmac)
|
||||
{
|
||||
return &edmac->chan.dev->device;
|
||||
@@ -226,6 +261,31 @@ static struct ep93xx_dma_chan *to_ep93xx_dma_chan(struct dma_chan *chan)
|
||||
return container_of(chan, struct ep93xx_dma_chan, chan);
|
||||
}
|
||||
|
||||
static inline bool ep93xx_dma_chan_is_m2p(struct dma_chan *chan)
|
||||
{
|
||||
if (device_is_compatible(chan->device->dev, "cirrus,ep9301-dma-m2p"))
|
||||
return true;
|
||||
|
||||
return !strcmp(dev_name(chan->device->dev), "ep93xx-dma-m2p");
|
||||
}
|
||||
|
||||
/*
|
||||
* ep93xx_dma_chan_direction - returns direction the channel can be used
|
||||
*
|
||||
* This function can be used in filter functions to find out whether the
|
||||
* channel supports given DMA direction. Only M2P channels have such
|
||||
* limitation, for M2M channels the direction is configurable.
|
||||
*/
|
||||
static inline enum dma_transfer_direction
|
||||
ep93xx_dma_chan_direction(struct dma_chan *chan)
|
||||
{
|
||||
if (!ep93xx_dma_chan_is_m2p(chan))
|
||||
return DMA_TRANS_NONE;
|
||||
|
||||
/* even channels are for TX, odd for RX */
|
||||
return (chan->chan_id % 2 == 0) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
|
||||
}
|
||||
|
||||
/**
|
||||
* ep93xx_dma_set_active - set new active descriptor chain
|
||||
* @edmac: channel
|
||||
@@ -318,10 +378,9 @@ static void m2p_set_control(struct ep93xx_dma_chan *edmac, u32 control)
|
||||
|
||||
static int m2p_hw_setup(struct ep93xx_dma_chan *edmac)
|
||||
{
|
||||
struct ep93xx_dma_data *data = edmac->chan.private;
|
||||
u32 control;
|
||||
|
||||
writel(data->port & 0xf, edmac->regs + M2P_PPALLOC);
|
||||
writel(edmac->dma_cfg.port & 0xf, edmac->regs + M2P_PPALLOC);
|
||||
|
||||
control = M2P_CONTROL_CH_ERROR_INT | M2P_CONTROL_ICE
|
||||
| M2P_CONTROL_ENABLE;
|
||||
@@ -458,16 +517,15 @@ static int m2p_hw_interrupt(struct ep93xx_dma_chan *edmac)
|
||||
|
||||
static int m2m_hw_setup(struct ep93xx_dma_chan *edmac)
|
||||
{
|
||||
const struct ep93xx_dma_data *data = edmac->chan.private;
|
||||
u32 control = 0;
|
||||
|
||||
if (!data) {
|
||||
if (edmac->dma_cfg.dir == DMA_MEM_TO_MEM) {
|
||||
/* This is memcpy channel, nothing to configure */
|
||||
writel(control, edmac->regs + M2M_CONTROL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (data->port) {
|
||||
switch (edmac->dma_cfg.port) {
|
||||
case EP93XX_DMA_SSP:
|
||||
/*
|
||||
* This was found via experimenting - anything less than 5
|
||||
@@ -477,7 +535,7 @@ static int m2m_hw_setup(struct ep93xx_dma_chan *edmac)
|
||||
control = (5 << M2M_CONTROL_PWSC_SHIFT);
|
||||
control |= M2M_CONTROL_NO_HDSK;
|
||||
|
||||
if (data->direction == DMA_MEM_TO_DEV) {
|
||||
if (edmac->dma_cfg.dir == DMA_MEM_TO_DEV) {
|
||||
control |= M2M_CONTROL_DAH;
|
||||
control |= M2M_CONTROL_TM_TX;
|
||||
control |= M2M_CONTROL_RSS_SSPTX;
|
||||
@@ -493,7 +551,7 @@ static int m2m_hw_setup(struct ep93xx_dma_chan *edmac)
|
||||
* This IDE part is totally untested. Values below are taken
|
||||
* from the EP93xx Users's Guide and might not be correct.
|
||||
*/
|
||||
if (data->direction == DMA_MEM_TO_DEV) {
|
||||
if (edmac->dma_cfg.dir == DMA_MEM_TO_DEV) {
|
||||
/* Worst case from the UG */
|
||||
control = (3 << M2M_CONTROL_PWSC_SHIFT);
|
||||
control |= M2M_CONTROL_DAH;
|
||||
@@ -548,7 +606,6 @@ static void m2m_fill_desc(struct ep93xx_dma_chan *edmac)
|
||||
|
||||
static void m2m_hw_submit(struct ep93xx_dma_chan *edmac)
|
||||
{
|
||||
struct ep93xx_dma_data *data = edmac->chan.private;
|
||||
u32 control = readl(edmac->regs + M2M_CONTROL);
|
||||
|
||||
/*
|
||||
@@ -574,7 +631,7 @@ static void m2m_hw_submit(struct ep93xx_dma_chan *edmac)
|
||||
control |= M2M_CONTROL_ENABLE;
|
||||
writel(control, edmac->regs + M2M_CONTROL);
|
||||
|
||||
if (!data) {
|
||||
if (edmac->dma_cfg.dir == DMA_MEM_TO_MEM) {
|
||||
/*
|
||||
* For memcpy channels the software trigger must be asserted
|
||||
* in order to start the memcpy operation.
|
||||
@@ -636,7 +693,7 @@ static int m2m_hw_interrupt(struct ep93xx_dma_chan *edmac)
|
||||
*/
|
||||
if (ep93xx_dma_advance_active(edmac)) {
|
||||
m2m_fill_desc(edmac);
|
||||
if (done && !edmac->chan.private) {
|
||||
if (done && edmac->dma_cfg.dir == DMA_MEM_TO_MEM) {
|
||||
/* Software trigger for memcpy channel */
|
||||
control = readl(edmac->regs + M2M_CONTROL);
|
||||
control |= M2M_CONTROL_START;
|
||||
@@ -867,25 +924,22 @@ static dma_cookie_t ep93xx_dma_tx_submit(struct dma_async_tx_descriptor *tx)
|
||||
static int ep93xx_dma_alloc_chan_resources(struct dma_chan *chan)
|
||||
{
|
||||
struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
|
||||
struct ep93xx_dma_data *data = chan->private;
|
||||
const char *name = dma_chan_name(chan);
|
||||
int ret, i;
|
||||
|
||||
/* Sanity check the channel parameters */
|
||||
if (!edmac->edma->m2m) {
|
||||
if (!data)
|
||||
if (edmac->dma_cfg.port < EP93XX_DMA_I2S1 ||
|
||||
edmac->dma_cfg.port > EP93XX_DMA_IRDA)
|
||||
return -EINVAL;
|
||||
if (data->port < EP93XX_DMA_I2S1 ||
|
||||
data->port > EP93XX_DMA_IRDA)
|
||||
return -EINVAL;
|
||||
if (data->direction != ep93xx_dma_chan_direction(chan))
|
||||
if (edmac->dma_cfg.dir != ep93xx_dma_chan_direction(chan))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (data) {
|
||||
switch (data->port) {
|
||||
if (edmac->dma_cfg.dir != DMA_MEM_TO_MEM) {
|
||||
switch (edmac->dma_cfg.port) {
|
||||
case EP93XX_DMA_SSP:
|
||||
case EP93XX_DMA_IDE:
|
||||
if (!is_slave_direction(data->direction))
|
||||
if (!is_slave_direction(edmac->dma_cfg.dir))
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
@@ -894,9 +948,6 @@ static int ep93xx_dma_alloc_chan_resources(struct dma_chan *chan)
|
||||
}
|
||||
}
|
||||
|
||||
if (data && data->name)
|
||||
name = data->name;
|
||||
|
||||
ret = clk_prepare_enable(edmac->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -1315,36 +1366,53 @@ static void ep93xx_dma_issue_pending(struct dma_chan *chan)
|
||||
ep93xx_dma_advance_work(to_ep93xx_dma_chan(chan));
|
||||
}
|
||||
|
||||
static int __init ep93xx_dma_probe(struct platform_device *pdev)
|
||||
static struct ep93xx_dma_engine *ep93xx_dma_of_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct ep93xx_dma_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
const struct ep93xx_edma_data *data;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct ep93xx_dma_engine *edma;
|
||||
struct dma_device *dma_dev;
|
||||
int ret, i;
|
||||
char dma_clk_name[5];
|
||||
int i;
|
||||
|
||||
edma = kzalloc(struct_size(edma, channels, pdata->num_channels), GFP_KERNEL);
|
||||
data = device_get_match_data(dev);
|
||||
if (!data)
|
||||
return ERR_PTR(dev_err_probe(dev, -ENODEV, "No device match found\n"));
|
||||
|
||||
edma = devm_kzalloc(dev, struct_size(edma, channels, data->num_channels),
|
||||
GFP_KERNEL);
|
||||
if (!edma)
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
edma->m2m = data->id;
|
||||
edma->num_channels = data->num_channels;
|
||||
dma_dev = &edma->dma_dev;
|
||||
edma->m2m = platform_get_device_id(pdev)->driver_data;
|
||||
edma->num_channels = pdata->num_channels;
|
||||
|
||||
INIT_LIST_HEAD(&dma_dev->channels);
|
||||
for (i = 0; i < pdata->num_channels; i++) {
|
||||
const struct ep93xx_dma_chan_data *cdata = &pdata->channels[i];
|
||||
for (i = 0; i < edma->num_channels; i++) {
|
||||
struct ep93xx_dma_chan *edmac = &edma->channels[i];
|
||||
|
||||
edmac->chan.device = dma_dev;
|
||||
edmac->regs = cdata->base;
|
||||
edmac->irq = cdata->irq;
|
||||
edmac->regs = devm_platform_ioremap_resource(pdev, i);
|
||||
if (IS_ERR(edmac->regs))
|
||||
return edmac->regs;
|
||||
|
||||
edmac->irq = fwnode_irq_get(dev_fwnode(dev), i);
|
||||
if (edmac->irq < 0)
|
||||
return ERR_PTR(edmac->irq);
|
||||
|
||||
edmac->edma = edma;
|
||||
|
||||
edmac->clk = clk_get(NULL, cdata->name);
|
||||
if (edma->m2m)
|
||||
snprintf(dma_clk_name, sizeof(dma_clk_name), "m2m%u", i);
|
||||
else
|
||||
snprintf(dma_clk_name, sizeof(dma_clk_name), "m2p%u", i);
|
||||
|
||||
edmac->clk = devm_clk_get(dev, dma_clk_name);
|
||||
if (IS_ERR(edmac->clk)) {
|
||||
dev_warn(&pdev->dev, "failed to get clock for %s\n",
|
||||
cdata->name);
|
||||
continue;
|
||||
dev_err_probe(dev, PTR_ERR(edmac->clk),
|
||||
"no %s clock found\n", dma_clk_name);
|
||||
return ERR_CAST(edmac->clk);
|
||||
}
|
||||
|
||||
spin_lock_init(&edmac->lock);
|
||||
@@ -1357,6 +1425,90 @@ static int __init ep93xx_dma_probe(struct platform_device *pdev)
|
||||
&dma_dev->channels);
|
||||
}
|
||||
|
||||
return edma;
|
||||
}
|
||||
|
||||
static bool ep93xx_m2p_dma_filter(struct dma_chan *chan, void *filter_param)
|
||||
{
|
||||
struct ep93xx_dma_chan *echan = to_ep93xx_dma_chan(chan);
|
||||
struct ep93xx_dma_chan_cfg *cfg = filter_param;
|
||||
|
||||
if (cfg->dir != ep93xx_dma_chan_direction(chan))
|
||||
return false;
|
||||
|
||||
echan->dma_cfg = *cfg;
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct dma_chan *ep93xx_m2p_dma_of_xlate(struct of_phandle_args *dma_spec,
|
||||
struct of_dma *ofdma)
|
||||
{
|
||||
struct ep93xx_dma_engine *edma = ofdma->of_dma_data;
|
||||
dma_cap_mask_t mask = edma->dma_dev.cap_mask;
|
||||
struct ep93xx_dma_chan_cfg dma_cfg;
|
||||
u8 port = dma_spec->args[0];
|
||||
u8 direction = dma_spec->args[1];
|
||||
|
||||
if (port > EP93XX_DMA_IRDA)
|
||||
return NULL;
|
||||
|
||||
if (!is_slave_direction(direction))
|
||||
return NULL;
|
||||
|
||||
dma_cfg.port = port;
|
||||
dma_cfg.dir = direction;
|
||||
|
||||
return __dma_request_channel(&mask, ep93xx_m2p_dma_filter, &dma_cfg, ofdma->of_node);
|
||||
}
|
||||
|
||||
static bool ep93xx_m2m_dma_filter(struct dma_chan *chan, void *filter_param)
|
||||
{
|
||||
struct ep93xx_dma_chan *echan = to_ep93xx_dma_chan(chan);
|
||||
struct ep93xx_dma_chan_cfg *cfg = filter_param;
|
||||
|
||||
echan->dma_cfg = *cfg;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct dma_chan *ep93xx_m2m_dma_of_xlate(struct of_phandle_args *dma_spec,
|
||||
struct of_dma *ofdma)
|
||||
{
|
||||
struct ep93xx_dma_engine *edma = ofdma->of_dma_data;
|
||||
dma_cap_mask_t mask = edma->dma_dev.cap_mask;
|
||||
struct ep93xx_dma_chan_cfg dma_cfg;
|
||||
u8 port = dma_spec->args[0];
|
||||
u8 direction = dma_spec->args[1];
|
||||
|
||||
if (!is_slave_direction(direction))
|
||||
return NULL;
|
||||
|
||||
switch (port) {
|
||||
case EP93XX_DMA_SSP:
|
||||
case EP93XX_DMA_IDE:
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dma_cfg.port = port;
|
||||
dma_cfg.dir = direction;
|
||||
|
||||
return __dma_request_channel(&mask, ep93xx_m2m_dma_filter, &dma_cfg, ofdma->of_node);
|
||||
}
|
||||
|
||||
static int ep93xx_dma_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct ep93xx_dma_engine *edma;
|
||||
struct dma_device *dma_dev;
|
||||
int ret;
|
||||
|
||||
edma = ep93xx_dma_of_probe(pdev);
|
||||
if (IS_ERR(edma))
|
||||
return PTR_ERR(edma);
|
||||
|
||||
dma_dev = &edma->dma_dev;
|
||||
|
||||
dma_cap_zero(dma_dev->cap_mask);
|
||||
dma_cap_set(DMA_SLAVE, dma_dev->cap_mask);
|
||||
dma_cap_set(DMA_CYCLIC, dma_dev->cap_mask);
|
||||
@@ -1393,21 +1545,46 @@ static int __init ep93xx_dma_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
ret = dma_async_device_register(dma_dev);
|
||||
if (unlikely(ret)) {
|
||||
for (i = 0; i < edma->num_channels; i++) {
|
||||
struct ep93xx_dma_chan *edmac = &edma->channels[i];
|
||||
if (!IS_ERR_OR_NULL(edmac->clk))
|
||||
clk_put(edmac->clk);
|
||||
}
|
||||
kfree(edma);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (edma->m2m) {
|
||||
ret = of_dma_controller_register(pdev->dev.of_node, ep93xx_m2m_dma_of_xlate,
|
||||
edma);
|
||||
} else {
|
||||
dev_info(dma_dev->dev, "EP93xx M2%s DMA ready\n",
|
||||
edma->m2m ? "M" : "P");
|
||||
ret = of_dma_controller_register(pdev->dev.of_node, ep93xx_m2p_dma_of_xlate,
|
||||
edma);
|
||||
}
|
||||
if (ret)
|
||||
goto err_dma_unregister;
|
||||
|
||||
dev_info(dma_dev->dev, "EP93xx M2%s DMA ready\n", edma->m2m ? "M" : "P");
|
||||
|
||||
return 0;
|
||||
|
||||
err_dma_unregister:
|
||||
dma_async_device_unregister(dma_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct ep93xx_edma_data edma_m2p = {
|
||||
.id = M2P_DMA,
|
||||
.num_channels = 10,
|
||||
};
|
||||
|
||||
static const struct ep93xx_edma_data edma_m2m = {
|
||||
.id = M2M_DMA,
|
||||
.num_channels = 2,
|
||||
};
|
||||
|
||||
static const struct of_device_id ep93xx_dma_of_ids[] = {
|
||||
{ .compatible = "cirrus,ep9301-dma-m2p", .data = &edma_m2p },
|
||||
{ .compatible = "cirrus,ep9301-dma-m2m", .data = &edma_m2m },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ep93xx_dma_of_ids);
|
||||
|
||||
static const struct platform_device_id ep93xx_dma_driver_ids[] = {
|
||||
{ "ep93xx-dma-m2p", 0 },
|
||||
{ "ep93xx-dma-m2m", 1 },
|
||||
@@ -1417,15 +1594,13 @@ static const struct platform_device_id ep93xx_dma_driver_ids[] = {
|
||||
static struct platform_driver ep93xx_dma_driver = {
|
||||
.driver = {
|
||||
.name = "ep93xx-dma",
|
||||
.of_match_table = ep93xx_dma_of_ids,
|
||||
},
|
||||
.id_table = ep93xx_dma_driver_ids,
|
||||
.probe = ep93xx_dma_probe,
|
||||
};
|
||||
|
||||
static int __init ep93xx_dma_module_init(void)
|
||||
{
|
||||
return platform_driver_probe(&ep93xx_dma_driver, ep93xx_dma_probe);
|
||||
}
|
||||
subsys_initcall(ep93xx_dma_module_init);
|
||||
module_platform_driver(ep93xx_dma_driver);
|
||||
|
||||
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
|
||||
MODULE_DESCRIPTION("EP93xx DMA driver");
|
||||
|
||||
@@ -1911,7 +1911,6 @@ static __poll_t fw_device_op_poll(struct file *file, poll_table * pt)
|
||||
|
||||
const struct file_operations fw_device_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.open = fw_device_op_open,
|
||||
.read = fw_device_op_read,
|
||||
.unlocked_ioctl = fw_device_op_ioctl,
|
||||
|
||||
@@ -2886,7 +2886,6 @@ static ssize_t reset_all_on_write(struct file *filp, const char __user *buf,
|
||||
static const struct file_operations fops_reset_counts = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = simple_open,
|
||||
.llseek = no_llseek,
|
||||
.write = reset_all_on_write,
|
||||
};
|
||||
|
||||
|
||||
@@ -950,7 +950,6 @@ static const struct file_operations scmi_dbg_raw_mode_reset_fops = {
|
||||
.open = scmi_dbg_raw_mode_open,
|
||||
.release = scmi_dbg_raw_mode_release,
|
||||
.write = scmi_dbg_raw_mode_reset_write,
|
||||
.llseek = no_llseek,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
@@ -960,7 +959,6 @@ static const struct file_operations scmi_dbg_raw_mode_message_fops = {
|
||||
.read = scmi_dbg_raw_mode_message_read,
|
||||
.write = scmi_dbg_raw_mode_message_write,
|
||||
.poll = scmi_dbg_raw_mode_message_poll,
|
||||
.llseek = no_llseek,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
@@ -977,7 +975,6 @@ static const struct file_operations scmi_dbg_raw_mode_message_async_fops = {
|
||||
.read = scmi_dbg_raw_mode_message_read,
|
||||
.write = scmi_dbg_raw_mode_message_async_write,
|
||||
.poll = scmi_dbg_raw_mode_message_poll,
|
||||
.llseek = no_llseek,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
@@ -1001,7 +998,6 @@ static const struct file_operations scmi_dbg_raw_mode_notification_fops = {
|
||||
.release = scmi_dbg_raw_mode_release,
|
||||
.read = scmi_test_dbg_raw_mode_notif_read,
|
||||
.poll = scmi_test_dbg_raw_mode_notif_poll,
|
||||
.llseek = no_llseek,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
@@ -1025,7 +1021,6 @@ static const struct file_operations scmi_dbg_raw_mode_errors_fops = {
|
||||
.release = scmi_dbg_raw_mode_release,
|
||||
.read = scmi_test_dbg_raw_mode_errors_read,
|
||||
.poll = scmi_test_dbg_raw_mode_errors_poll,
|
||||
.llseek = no_llseek,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
||||
@@ -309,7 +309,6 @@ static const struct file_operations efi_capsule_fops = {
|
||||
.open = efi_capsule_open,
|
||||
.write = efi_capsule_write,
|
||||
.release = efi_capsule_release,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static struct miscdevice efi_capsule_misc = {
|
||||
|
||||
@@ -434,12 +434,17 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
|
||||
"%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n",
|
||||
pfx, pcie->bridge.secondary_status, pcie->bridge.control);
|
||||
|
||||
/* Fatal errors call __ghes_panic() before AER handler prints this */
|
||||
if ((pcie->validation_bits & CPER_PCIE_VALID_AER_INFO) &&
|
||||
(gdata->error_severity & CPER_SEV_FATAL)) {
|
||||
/*
|
||||
* Print all valid AER info. Record may be from BERT (boot-time) or GHES (run-time).
|
||||
*
|
||||
* Fatal errors call __ghes_panic() before AER handler prints this.
|
||||
*/
|
||||
if (pcie->validation_bits & CPER_PCIE_VALID_AER_INFO) {
|
||||
struct aer_capability_regs *aer;
|
||||
|
||||
aer = (struct aer_capability_regs *)pcie->aer_info;
|
||||
printk("%saer_cor_status: 0x%08x, aer_cor_mask: 0x%08x\n",
|
||||
pfx, aer->cor_status, aer->cor_mask);
|
||||
printk("%saer_uncor_status: 0x%08x, aer_uncor_mask: 0x%08x\n",
|
||||
pfx, aer->uncor_status, aer->uncor_mask);
|
||||
printk("%saer_uncor_severity: 0x%08x\n",
|
||||
|
||||
@@ -349,7 +349,7 @@ static void __init efi_debugfs_init(void)
|
||||
int i = 0;
|
||||
|
||||
efi_debugfs = debugfs_create_dir("efi", NULL);
|
||||
if (IS_ERR_OR_NULL(efi_debugfs))
|
||||
if (IS_ERR(efi_debugfs))
|
||||
return;
|
||||
|
||||
for_each_efi_memory_desc(md) {
|
||||
|
||||
@@ -96,7 +96,7 @@ static void efi_retrieve_tcg2_eventlog(int version, efi_physical_addr_t log_loca
|
||||
}
|
||||
|
||||
/* Allocate space for the logs and copy them. */
|
||||
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
|
||||
status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
|
||||
sizeof(*log_tbl) + log_size, (void **)&log_tbl);
|
||||
|
||||
if (status != EFI_SUCCESS) {
|
||||
|
||||
@@ -750,7 +750,6 @@ static const struct file_operations efi_test_fops = {
|
||||
.unlocked_ioctl = efi_test_ioctl,
|
||||
.open = efi_test_open,
|
||||
.release = efi_test_close,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static struct miscdevice efi_test_dev = {
|
||||
|
||||
@@ -386,7 +386,6 @@ static const struct file_operations do_sign_fops = {
|
||||
.open = rwtm_debug_open,
|
||||
.read = do_sign_read,
|
||||
.write = do_sign_write,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static void rwtm_debugfs_release(void *root)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user