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:
Matthias Maennich
2024-10-03 15:51:56 +00:00
committed by Treehugger Robot
326 changed files with 5569 additions and 5418 deletions
@@ -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,
+1
View File
@@ -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
+223 -16
View File
@@ -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 */
-246
View File
@@ -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
-1
View File
@@ -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
+4
View File
@@ -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
+125
View File
@@ -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;
};
};
};
};
};
&eth0 {
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";
};
+181
View File
@@ -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>;
};
};
&eth0 {
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";
};
+145
View File
@@ -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>;
};
};
&eth0 {
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";
};
+444
View File
@@ -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";
};
};
+10 -10
View File
@@ -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
-11
View File
@@ -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
-733
View File
@@ -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
-114
View File
@@ -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);
-368
View File
@@ -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
-38
View File
@@ -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
-111
View File
@@ -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 */
-25
View File
@@ -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
-76
View File
@@ -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
-42
View File
@@ -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
-212
View File
@@ -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 */
-143
View File
@@ -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);
}
-422
View File
@@ -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
-94
View File
@@ -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_ */
-319
View File
@@ -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
+1 -2
View File
@@ -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
-1
View File
@@ -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,
-1
View File
@@ -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,
};
-1
View File
@@ -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 = {
-1
View File
@@ -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;
-1
View File
@@ -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 = {
-1
View File
@@ -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)
+1 -2
View 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)
-1
View File
@@ -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 = {
-1
View File
@@ -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 = {
-2
View File
@@ -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,
-1
View File
@@ -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,
+1 -2
View File
@@ -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);
-1
View File
@@ -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
View File
@@ -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,
-1
View File
@@ -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 = {
+1 -47
View File
@@ -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
*
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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;
+30
View File
@@ -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.
*
+9 -5
View File
@@ -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;
}
+1 -1
View File
@@ -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,
-2
View File
@@ -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)
-1
View File
@@ -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 = {
-1
View File
@@ -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,
-1
View File
@@ -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 = {
+1 -1
View File
@@ -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,
-2
View File
@@ -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)
-1
View File
@@ -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,
-1
View File
@@ -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 = {
-1
View File
@@ -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 */
-1
View File
@@ -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,
-1
View File
@@ -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 = {
-1
View File
@@ -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)
-1
View File
@@ -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,
-1
View File
@@ -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 */
-1
View File
@@ -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 = {
-1
View File
@@ -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,
-1
View File
@@ -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,
-1
View File
@@ -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,
-1
View File
@@ -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,
};
/*
+8
View File
@@ -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
+1
View File
@@ -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
+850
View File
@@ -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");
-1
View File
@@ -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
View File
@@ -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");
-1
View File
@@ -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,
-1
View File
@@ -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,
};
-5
View File
@@ -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,
};
-1
View File
@@ -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 = {
+8 -3
View File
@@ -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",
+1 -1
View File
@@ -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) {
+1 -1
View File
@@ -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) {
-1
View File
@@ -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 = {
-1
View File
@@ -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