Commit 3af49062 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mfd-next-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd

Pull MFD updates from Lee Jones:
 "New Drivers:
   - Add support for  Renesas RZ/G2L MTU3

  New Device Support:
   - Add support for Lenovo Yoga Book X90F to Intel CHT WC
   - Add support for MAX5970 and MAX5978 to Simple MFD (I2C)
   - Add support for Meteor Lake PCH-S LPSS PCI to Intel LPSS PCI
   - Add support for AXP15060 PMIC to X-Powers PMIC collection

  Remove Device Support:
   - Remove support for Samsung 5M8751 and S5M8763 PMIC devices

  New Functionality:
   - Convert deprecated QCOM IRQ Chip to config registers
   - Add support for 32-bit address spaces to Renesas SMUs

  Fix-ups:
   - Make use of APIs / MACROs designed to simplify and demystify
   - Add / improve Device Tree bindings
   - Memory saving struct layout optimisations
   - Remove old / deprecated functionality
   - Factor out unassigned register addresses from ranges
   - Trivial: Spelling fixes, renames and coding style fixes
   - Rid 'defined but not used' warnings
   - Remove ineffective casts and pointer stubs

  Bug Fixes:
   - Fix incorrectly non-inverted mask/unmask IRQs on QCOM platforms
   - Remove MODULE_*() helpers from non-tristate drivers
   - Do not attempt to use out-of-range memory addresses associated with io_base
   - Provide missing export helpers
   - Fix remap bulk read optimisation fallout
   - Fix memory leak issues in error paths"

* tag 'mfd-next-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (88 commits)
  dt-bindings: mfd: ti,j721e-system-controller: Add SoC chip ID
  leds: bd2606mvv: Driver for the Rohm 6 Channel i2c LED driver
  dt-bindings: mfd: qcom,spmi-pmic: Document flash LED controller
  dt-bindings: mfd: x-powers,axp152: Document the AXP15060 variant
  mfd: axp20x: Add support for AXP15060 PMIC
  dt-bindings: mfd: x-powers,axp152: Document the AXP313a variant
  counter: rz-mtu3-cnt: Unlock on error in rz_mtu3_count_ceiling_write()
  dt-bindings: mfd: dlg,da9063: Document voltage monitoring
  dt-bindings: mfd: stm32: Remove unnecessary blank lines
  dt-bindings: mfd: qcom,spmi-pmic: Use generic ADC node name in examples
  dt-bindings: mfd: syscon: Add nuvoton,ma35d1-sys compatible
  MAINTAINERS: Add entries for Renesas RZ/G2L MTU3a counter driver
  counter: Add Renesas RZ/G2L MTU3a counter driver
  Documentation: ABI: sysfs-bus-counter: add cascade_counts_enable and external_input_phase_clock_select
  mfd: Add Renesas RZ/G2L MTU3a core driver
  dt-bindings: timer: Document RZ/G2L MTU3a bindings
  mfd: rsmu_i2c: Convert to i2c's .probe_new() again
  mfd: intel-lpss: Add Intel Meteor Lake PCH-S LPSS PCI IDs
  mfd: dln2: Fix memory leak in dln2_probe()
  mfd: axp20x: Fix axp288 writable-ranges
  ...
parents c5eb8bf7 9e9ff392
What: /sys/bus/counter/devices/counterX/cascade_counts_enable
KernelVersion: 6.4
Contact: linux-iio@vger.kernel.org
Description:
Indicates the cascading of Counts on Counter X.
Valid attribute values are boolean.
What: /sys/bus/counter/devices/counterX/external_input_phase_clock_select
KernelVersion: 6.4
Contact: linux-iio@vger.kernel.org
Description:
Selects the external clock pin for phase counting mode of
Counter X.
MTCLKA-MTCLKB:
MTCLKA and MTCLKB pins are selected for the external
phase clock.
MTCLKC-MTCLKD:
MTCLKC and MTCLKD pins are selected for the external
phase clock.
What: /sys/bus/counter/devices/counterX/external_input_phase_clock_select_available
KernelVersion: 6.4
Contact: linux-iio@vger.kernel.org
Description:
Discrete set of available values for the respective device
configuration are listed in this file.
What: /sys/bus/counter/devices/counterX/countY/count
KernelVersion: 5.2
Contact: linux-iio@vger.kernel.org
......@@ -215,6 +245,8 @@ Contact: linux-iio@vger.kernel.org
Description:
This attribute indicates the number of overflows of count Y.
What: /sys/bus/counter/devices/counterX/cascade_counts_enable_component_id
What: /sys/bus/counter/devices/counterX/external_input_phase_clock_select_component_id
What: /sys/bus/counter/devices/counterX/countY/capture_component_id
What: /sys/bus/counter/devices/counterX/countY/ceiling_component_id
What: /sys/bus/counter/devices/counterX/countY/floor_component_id
......
......@@ -36,7 +36,7 @@ properties:
clock-controller:
# Child node
type: object
$ref: "../clock/canaan,k210-clk.yaml"
$ref: ../clock/canaan,k210-clk.yaml
description:
Clock controller for the SoC clocks. This child node definition
should follow the bindings specified in
......@@ -45,7 +45,7 @@ properties:
reset-controller:
# Child node
type: object
$ref: "../reset/canaan,k210-rst.yaml"
$ref: ../reset/canaan,k210-rst.yaml
description:
Reset controller for the SoC. This child node definition
should follow the bindings specified in
......@@ -54,7 +54,7 @@ properties:
syscon-reboot:
# Child node
type: object
$ref: "../power/reset/syscon-reboot.yaml"
$ref: ../power/reset/syscon-reboot.yaml
description:
Reboot method for the SoC. This child node definition
should follow the bindings specified in
......
......@@ -65,7 +65,7 @@ properties:
ARM Cortex M4 Co-processor. Contains the name of the rpmsg
device. Used to match the subnode to the rpmsg device announced by
the SCP.
$ref: "/schemas/types.yaml#/definitions/string"
$ref: /schemas/types.yaml#/definitions/string
spi-max-frequency: true
......@@ -94,23 +94,23 @@ properties:
const: 0
typec:
$ref: "/schemas/chrome/google,cros-ec-typec.yaml#"
$ref: /schemas/chrome/google,cros-ec-typec.yaml#
ec-pwm:
$ref: "/schemas/pwm/google,cros-ec-pwm.yaml#"
$ref: /schemas/pwm/google,cros-ec-pwm.yaml#
deprecated: true
pwm:
$ref: "/schemas/pwm/google,cros-ec-pwm.yaml#"
$ref: /schemas/pwm/google,cros-ec-pwm.yaml#
kbd-led-backlight:
$ref: "/schemas/chrome/google,cros-kbd-led-backlight.yaml#"
$ref: /schemas/chrome/google,cros-kbd-led-backlight.yaml#
keyboard-controller:
$ref: "/schemas/input/google,cros-ec-keyb.yaml#"
$ref: /schemas/input/google,cros-ec-keyb.yaml#
proximity:
$ref: "/schemas/iio/proximity/google,cros-ec-mkbp-proximity.yaml#"
$ref: /schemas/iio/proximity/google,cros-ec-mkbp-proximity.yaml#
codecs:
type: object
......@@ -126,7 +126,7 @@ properties:
patternProperties:
"^ec-codec@[a-f0-9]+$":
type: object
$ref: "/schemas/sound/google,cros-ec-codec.yaml#"
$ref: /schemas/sound/google,cros-ec-codec.yaml#
required:
- "#address-cells"
......@@ -151,15 +151,15 @@ properties:
patternProperties:
"^i2c-tunnel[0-9]*$":
type: object
$ref: "/schemas/i2c/google,cros-ec-i2c-tunnel.yaml#"
$ref: /schemas/i2c/google,cros-ec-i2c-tunnel.yaml#
"^regulator@[0-9]+$":
type: object
$ref: "/schemas/regulator/google,cros-ec-regulator.yaml#"
$ref: /schemas/regulator/google,cros-ec-regulator.yaml#
"^extcon[0-9]*$":
type: object
$ref: "/schemas/extcon/extcon-usbc-cros-ec.yaml#"
$ref: /schemas/extcon/extcon-usbc-cros-ec.yaml#
required:
- compatible
......
......@@ -53,7 +53,7 @@ properties:
'^ldo[0-9]+$':
type: object
$ref: "/schemas/regulator/regulator.yaml#"
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
......
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/maxim,max5970.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Regulator for MAX5970 Smart Switch from Maxim Integrated
maintainers:
- Patrick Rudolph <patrick.rudolph@9elements.com>
description: |
The smart switch provides no output regulation, but independent fault protection
and voltage and current sensing.
Programming is done through I2C bus.
Datasheets:
https://datasheets.maximintegrated.com/en/ds/MAX5970.pdf
https://datasheets.maximintegrated.com/en/ds/MAX5978.pdf
properties:
compatible:
enum:
- maxim,max5970
- maxim,max5978
reg:
maxItems: 1
interrupts:
maxItems: 1
leds:
type: object
description:
Properties for four LEDS.
properties:
"#address-cells":
const: 1
"#size-cells":
const: 0
patternProperties:
"^led@[0-3]$":
$ref: /schemas/leds/common.yaml#
type: object
additionalProperties: false
vss1-supply:
description: Supply of the first channel.
vss2-supply:
description: Supply of the second channel.
regulators:
type: object
description:
Properties for both hot swap control/switch.
patternProperties:
"^sw[0-1]$":
$ref: /schemas/regulator/regulator.yaml#
type: object
properties:
shunt-resistor-micro-ohms:
description: |
The value of current sense resistor in microohms.
required:
- shunt-resistor-micro-ohms
unevaluatedProperties: false
additionalProperties: false
required:
- compatible
- reg
- regulators
- vss1-supply
allOf:
- if:
properties:
compatible:
enum:
- maxim,max5970
then:
required:
- vss2-supply
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
regulator@3a {
compatible = "maxim,max5978";
reg = <0x3a>;
vss1-supply = <&p3v3>;
regulators {
sw0_ref_0: sw0 {
shunt-resistor-micro-ohms = <12000>;
};
};
leds {
#address-cells = <1>;
#size-cells = <0>;
led@0 {
reg = <0>;
label = "led0";
default-state = "on";
};
led@1 {
reg = <1>;
label = "led1";
default-state = "on";
};
};
};
};
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
regulator@3a {
compatible = "maxim,max5970";
reg = <0x3a>;
vss1-supply = <&p3v3>;
vss2-supply = <&p5v>;
regulators {
sw0_ref_1: sw0 {
shunt-resistor-micro-ohms = <12000>;
};
sw1_ref_1: sw1 {
shunt-resistor-micro-ohms = <10000>;
};
};
};
};
...
......@@ -33,6 +33,7 @@ properties:
compatible:
items:
- enum:
- qcom,pm2250
- qcom,pm6125
- qcom,pm6150
- qcom,pm6150l
......@@ -78,6 +79,7 @@ properties:
- qcom,pmk8350
- qcom,pmk8550
- qcom,pmm8155au
- qcom,pmm8654au
- qcom,pmp8074
- qcom,pmr735a
- qcom,pmr735b
......@@ -115,6 +117,7 @@ patternProperties:
type: object
oneOf:
- $ref: /schemas/iio/adc/qcom,spmi-iadc.yaml#
- $ref: /schemas/iio/adc/qcom,spmi-rradc.yaml#
- $ref: /schemas/iio/adc/qcom,spmi-vadc.yaml#
"^adc-tm@[0-9a-f]+$":
......@@ -135,6 +138,14 @@ patternProperties:
type: object
$ref: /schemas/pinctrl/qcom,pmic-gpio.yaml#
"^led-controller@[0-9a-f]+$":
type: object
$ref: /schemas/leds/qcom,spmi-flash-led.yaml#
"^nvram@[0-9a-f]+$":
type: object
$ref: /schemas/nvmem/qcom,spmi-sdam.yaml#
"pon@[0-9a-f]+$":
type: object
$ref: /schemas/power/reset/qcom,pon.yaml#
......@@ -276,12 +287,12 @@ examples:
#size-cells = <0>;
#io-channel-cells = <1>;
adc-chan@6 {
channel@6 {
reg = <ADC5_DIE_TEMP>;
label = "die_temp";
};
adc-chan@4f {
channel@4f {
reg = <ADC5_AMUX_THM3_100K_PU>;
qcom,ratiometric;
qcom,hw-settle-time = <200>;
......
......@@ -25,12 +25,16 @@ properties:
- qcom,sc8280xp-tcsr
- qcom,sdm630-tcsr
- qcom,sdm845-tcsr
- qcom,sdx55-tcsr
- qcom,sdx65-tcsr
- qcom,sm8150-tcsr
- qcom,sm8450-tcsr
- qcom,tcsr-apq8064
- qcom,tcsr-apq8084
- qcom,tcsr-ipq5332
- qcom,tcsr-ipq6018
- qcom,tcsr-ipq8064
- qcom,tcsr-ipq9574
- qcom,tcsr-mdm9615
- qcom,tcsr-msm8226
- qcom,tcsr-msm8660
......
......@@ -49,7 +49,7 @@ patternProperties:
"rtc@[0-9a-f]+$":
type: object
$ref: "../rtc/qcom-pm8xxx-rtc.yaml"
$ref: ../rtc/qcom-pm8xxx-rtc.yaml
required:
- compatible
......
......@@ -46,7 +46,7 @@ properties:
rohm,clkout-open-drain:
description: clk32kout mode. Set to 1 for "open-drain" or 0 for "cmos".
$ref: "/schemas/types.yaml#/definitions/uint32"
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 1
......
......@@ -46,7 +46,7 @@ properties:
rohm,clkout-open-drain:
description: clk32kout mode. Set to 1 for "open-drain" or 0 for "cmos".
$ref: "/schemas/types.yaml#/definitions/uint32"
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 1
......
......@@ -56,6 +56,7 @@ properties:
- microchip,lan966x-cpu-syscon
- microchip,sparx5-cpu-syscon
- mstar,msc313-pmsleep
- nuvoton,ma35d1-sys
- nuvoton,wpcm450-shm
- rockchip,px30-qos
- rockchip,rk3036-qos
......@@ -67,6 +68,7 @@ properties:
- rockchip,rk3568-qos
- rockchip,rk3588-qos
- rockchip,rv1126-qos
- starfive,jh7100-sysmain
- const: syscon
......
......@@ -62,6 +62,12 @@ patternProperties:
description:
The phy node corresponding to the ethernet MAC.
"^chipid@[0-9a-f]+$":
type: object
$ref: /schemas/hwinfo/ti,k3-socinfo.yaml#
description:
The node corresponding to SoC chip identification.
required:
- compatible
- reg
......@@ -99,5 +105,10 @@ examples:
reg = <0x4140 0x18>;
#clock-cells = <1>;
};
chipid@14 {
compatible = "ti,am654-chipid";
reg = <0x14 0x4>;
};
};
...
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (C) 2022-2023 Texas Instruments Incorporated - https://www.ti.com/
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/ti,nspire-misc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TI Nspire MISC hardware block
maintainers:
- Andrew Davis <afd@ti.com>
description:
System controller node represents a register region containing a set
of miscellaneous registers. The registers are not cohesive enough to
represent as any specific type of device. Currently there is a reset
controller.
properties:
compatible:
items:
- enum:
- ti,nspire-misc
- const: syscon
- const: simple-mfd
reg:
maxItems: 1
reboot:
$ref: /schemas/power/reset/syscon-reboot.yaml#
required:
- compatible
- reg
- reboot
additionalProperties: false
examples:
- |
misc: misc@900a0000 {
compatible = "ti,nspire-misc", "syscon", "simple-mfd";
reg = <0x900a0000 0x1000>;
reboot {
compatible = "syscon-reboot";
offset = <0x08>;
value = <0x02>;
};
};
......@@ -156,7 +156,7 @@ properties:
entry has a value that is out of range for a 16 bit register then the
chip default will be used. If present exactly five values must be
specified.
$ref: "/schemas/types.yaml#/definitions/uint32-array"
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
maxItems: 5
......
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: "http://devicetree.org/schemas/mfd/x-powers,ac100.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
$id: http://devicetree.org/schemas/mfd/x-powers,ac100.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: X-Powers AC100
......
......@@ -47,9 +47,8 @@ allOf:
- x-powers,axp209
then:
not:
required:
- x-powers,drive-vbus-en
properties:
x-powers,drive-vbus-en: false
- if:
not:
......@@ -59,14 +58,9 @@ allOf:
const: x-powers,axp806
then:
allOf:
- not:
required:
- x-powers,self-working-mode
- not:
required:
- x-powers,master-mode
properties:
x-powers,self-working-mode: false
x-powers,master-mode: false
- if:
not:
......@@ -79,6 +73,18 @@ allOf:
required:
- interrupts
- if:
properties:
compatible:
contains:
enum:
- x-powers,axp313a
- x-powers,axp15060
then:
properties:
x-powers,dcdc-freq: false
properties:
compatible:
oneOf:
......@@ -88,10 +94,12 @@ properties:
- x-powers,axp209
- x-powers,axp221
- x-powers,axp223
- x-powers,axp313a
- x-powers,axp803
- x-powers,axp806
- x-powers,axp809
- x-powers,axp813
- x-powers,axp15060
- items:
- const: x-powers,axp228
- const: x-powers,axp221
......@@ -260,7 +268,7 @@ properties:
Defines the work frequency of DC-DC in kHz.
patternProperties:
"^(([a-f])?ldo[0-9]|dcdc[0-7a-e]|ldo(_|-)io(0|1)|(dc1)?sw|rtc(_|-)ldo|drivevbus|dc5ldo)$":
"^(([a-f])?ldo[0-9]|dcdc[0-7a-e]|ldo(_|-)io(0|1)|(dc1)?sw|rtc(_|-)ldo|cpusldo|drivevbus|dc5ldo)$":
$ref: /schemas/regulator/regulator.yaml#
type: object
unevaluatedProperties: false
......
......@@ -2,8 +2,8 @@
# Copyright 2019 Bootlin
%YAML 1.2
---
$id: "http://devicetree.org/schemas/mfd/xylon,logicvc.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
$id: http://devicetree.org/schemas/mfd/xylon,logicvc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Xylon LogiCVC multi-function device
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/timer/renesas,rz-mtu3.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas RZ/G2L Multi-Function Timer Pulse Unit 3 (MTU3a)
maintainers:
- Biju Das <biju.das.jz@bp.renesas.com>
description: |
This hardware block consists of eight 16-bit timer channels and one
32- bit timer channel. It supports the following specifications:
- Pulse input/output: 28 lines max.
- Pulse input 3 lines
- Count clock 11 clocks for each channel (14 clocks for MTU0, 12 clocks
for MTU2, and 10 clocks for MTU5, four clocks for MTU1-MTU2 combination
(when LWA = 1))
- Operating frequency Up to 100 MHz
- Available operations [MTU0 to MTU4, MTU6, MTU7, and MTU8]
- Waveform output on compare match
- Input capture function (noise filter setting available)
- Counter-clearing operation
- Simultaneous writing to multiple timer counters (TCNT)
(excluding MTU8).
- Simultaneous clearing on compare match or input capture
(excluding MTU8).
- Simultaneous input and output to registers in synchronization with
counter operations (excluding MTU8).
- Up to 12-phase PWM output in combination with synchronous operation
(excluding MTU8)
- [MTU0 MTU3, MTU4, MTU6, MTU7, and MTU8]
- Buffer operation specifiable
- [MTU1, MTU2]
- Phase counting mode can be specified independently
- 32-bit phase counting mode can be specified for interlocked operation
of MTU1 and MTU2 (when TMDR3.LWA = 1)
- Cascade connection operation available
- [MTU3, MTU4, MTU6, and MTU7]
- Through interlocked operation of MTU3/4 and MTU6/7, the positive and
negative signals in six phases (12 phases in total) can be output in
complementary PWM and reset-synchronized PWM operation.
- In complementary PWM mode, values can be transferred from buffer
registers to temporary registers at crests and troughs of the timer-
counter values or when the buffer registers (TGRD registers in MTU4
and MTU7) are written to.
- Double-buffering selectable in complementary PWM mode.
- [MTU3 and MTU4]
- Through interlocking with MTU0, a mode for driving AC synchronous
motors (brushless DC motors) by using complementary PWM output and
reset-synchronized PWM output is settable and allows the selection
of two types of waveform output (chopping or level).
- [MTU5]
- Capable of operation as a dead-time compensation counter.
- [MTU0/MTU5, MTU1, MTU2, and MTU8]
- 32-bit phase counting mode specifiable by combining MTU1 and MTU2 and
through interlocked operation with MTU0/MTU5 and MTU8.
- Interrupt-skipping function
- In complementary PWM mode, interrupts on crests and troughs of counter
values and triggers to start conversion by the A/D converter can be
skipped.
- Interrupt sources: 43 sources.
- Buffer operation:
- Automatic transfer of register data (transfer from the buffer
register to the timer register).
- Trigger generation
- A/D converter start triggers can be generated
- A/D converter start request delaying function enables A/D converter
to be started with any desired timing and to be synchronized with
PWM output.
- Low power consumption function
- The MTU3a can be placed in the module-stop state.
There are two phase counting modes. 16-bit phase counting mode in which
MTU1 and MTU2 operate independently, and cascade connection 32-bit phase
counting mode in which MTU1 and MTU2 are cascaded.
In phase counting mode, the phase difference between two external input
clocks is detected and the corresponding TCNT is incremented or
decremented.
The below counters are supported
count0 - MTU1 16-bit phase counting
count1 - MTU2 16-bit phase counting
count2 - MTU1+ MTU2 32-bit phase counting
The module supports PWM mode{1,2}, Reset-synchronized PWM mode and
complementary PWM mode{1,2,3}.
In complementary PWM mode, six positive-phase and six negative-phase PWM
waveforms (12 phases in total) with dead time can be output by
combining MTU{3,4} and MTU{6,7}.
The below pwm channels are supported in pwm mode 1.
pwm0 - MTU0.MTIOC0A PWM mode 1
pwm1 - MTU0.MTIOC0C PWM mode 1
pwm2 - MTU1.MTIOC1A PWM mode 1
pwm3 - MTU2.MTIOC2A PWM mode 1
pwm4 - MTU3.MTIOC3A PWM mode 1
pwm5 - MTU3.MTIOC3C PWM mode 1
pwm6 - MTU4.MTIOC4A PWM mode 1
pwm7 - MTU4.MTIOC4C PWM mode 1
pwm8 - MTU6.MTIOC6A PWM mode 1
pwm9 - MTU6.MTIOC6C PWM mode 1
pwm10 - MTU7.MTIOC7A PWM mode 1
pwm11 - MTU7.MTIOC7C PWM mode 1
properties:
compatible:
items:
- enum:
- renesas,r9a07g044-mtu3 # RZ/G2{L,LC}
- renesas,r9a07g054-mtu3 # RZ/V2L
- const: renesas,rz-mtu3
reg:
maxItems: 1
interrupts:
items:
- description: MTU0.TGRA input capture/compare match
- description: MTU0.TGRB input capture/compare match
- description: MTU0.TGRC input capture/compare match
- description: MTU0.TGRD input capture/compare match
- description: MTU0.TCNT overflow
- description: MTU0.TGRE compare match
- description: MTU0.TGRF compare match
- description: MTU1.TGRA input capture/compare match
- description: MTU1.TGRB input capture/compare match
- description: MTU1.TCNT overflow
- description: MTU1.TCNT underflow
- description: MTU2.TGRA input capture/compare match
- description: MTU2.TGRB input capture/compare match
- description: MTU2.TCNT overflow
- description: MTU2.TCNT underflow
- description: MTU3.TGRA input capture/compare match
- description: MTU3.TGRB input capture/compare match
- description: MTU3.TGRC input capture/compare match
- description: MTU3.TGRD input capture/compare match
- description: MTU3.TCNT overflow
- description: MTU4.TGRA input capture/compare match
- description: MTU4.TGRB input capture/compare match
- description: MTU4.TGRC input capture/compare match
- description: MTU4.TGRD input capture/compare match
- description: MTU4.TCNT overflow/underflow
- description: MTU5.TGRU input capture/compare match
- description: MTU5.TGRV input capture/compare match
- description: MTU5.TGRW input capture/compare match
- description: MTU6.TGRA input capture/compare match
- description: MTU6.TGRB input capture/compare match
- description: MTU6.TGRC input capture/compare match
- description: MTU6.TGRD input capture/compare match
- description: MTU6.TCNT overflow
- description: MTU7.TGRA input capture/compare match
- description: MTU7.TGRB input capture/compare match
- description: MTU7.TGRC input capture/compare match
- description: MTU7.TGRD input capture/compare match
- description: MTU7.TCNT overflow/underflow
- description: MTU8.TGRA input capture/compare match
- description: MTU8.TGRB input capture/compare match
- description: MTU8.TGRC input capture/compare match
- description: MTU8.TGRD input capture/compare match
- description: MTU8.TCNT overflow
- description: MTU8.TCNT underflow
interrupt-names:
items:
- const: tgia0
- const: tgib0
- const: tgic0
- const: tgid0
- const: tgiv0
- const: tgie0
- const: tgif0
- const: tgia1
- const: tgib1
- const: tgiv1
- const: tgiu1
- const: tgia2
- const: tgib2
- const: tgiv2
- const: tgiu2
- const: tgia3
- const: tgib3
- const: tgic3
- const: tgid3
- const: tgiv3
- const: tgia4
- const: tgib4
- const: tgic4
- const: tgid4
- const: tgiv4
- const: tgiu5
- const: tgiv5
- const: tgiw5
- const: tgia6
- const: tgib6
- const: tgic6
- const: tgid6
- const: tgiv6
- const: tgia7
- const: tgib7
- const: tgic7
- const: tgid7
- const: tgiv7
- const: tgia8
- const: tgib8
- const: tgic8
- const: tgid8
- const: tgiv8
- const: tgiu8
clocks:
maxItems: 1
power-domains:
maxItems: 1
resets:
maxItems: 1
"#pwm-cells":
const: 2
required:
- compatible
- reg
- interrupts
- interrupt-names
- clocks
- power-domains
- resets
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/r9a07g044-cpg.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
mtu3: timer@10001200 {
compatible = "renesas,r9a07g044-mtu3", "renesas,rz-mtu3";
reg = <0x10001200 0xb00>;
interrupts = <GIC_SPI 170 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 171 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 172 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 173 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 174 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 175 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 176 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 177 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 178 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 179 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 180 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 181 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 182 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 183 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 184 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 185 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 186 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 187 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 188 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 189 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 190 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 191 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 192 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 193 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 194 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 195 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 196 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 197 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 198 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 199 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 200 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 201 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 202 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 203 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 204 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 205 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 206 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 207 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 208 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 209 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 210 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 211 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 212 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 213 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0", "tgiv0", "tgie0",
"tgif0",
"tgia1", "tgib1", "tgiv1", "tgiu1",
"tgia2", "tgib2", "tgiv2", "tgiu2",
"tgia3", "tgib3", "tgic3", "tgid3", "tgiv3",
"tgia4", "tgib4", "tgic4", "tgid4", "tgiv4",
"tgiu5", "tgiv5", "tgiw5",
"tgia6", "tgib6", "tgic6", "tgid6", "tgiv6",
"tgia7", "tgib7", "tgic7", "tgid7", "tgiv7",
"tgia8", "tgib8", "tgic8", "tgid8", "tgiv8", "tgiu8";
clocks = <&cpg CPG_MOD R9A07G044_MTU_X_MCK_MTU3>;
power-domains = <&cpg>;
resets = <&cpg R9A07G044_MTU_X_PRESET_MTU3>;
#pwm-cells = <2>;
};
......@@ -17972,6 +17972,14 @@ S: Supported
F: Documentation/devicetree/bindings/iio/adc/renesas,rzg2l-adc.yaml
F: drivers/iio/adc/rzg2l_adc.c
RENESAS RZ/G2L MTU3a COUNTER DRIVER
M: Biju Das <biju.das.jz@bp.renesas.com>
L: linux-iio@vger.kernel.org
L: linux-renesas-soc@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/timer/renesas,rz-mtu3.yaml
F: drivers/counter/rz-mtu3-cnt.c
RENESAS RZ/N1 A5PSW SWITCH DRIVER
M: Clément Léger <clement.leger@bootlin.com>
L: linux-renesas-soc@vger.kernel.org
......
......@@ -73,6 +73,17 @@ config MICROCHIP_TCB_CAPTURE
To compile this driver as a module, choose M here: the
module will be called microchip-tcb-capture.
config RZ_MTU3_CNT
tristate "Renesas RZ/G2L MTU3a counter driver"
depends on RZ_MTU3 || COMPILE_TEST
help
Enable support for MTU3a counter driver found on Renesas RZ/G2L alike
SoCs. This IP supports both 16-bit and 32-bit phase counting mode
support.
To compile this driver as a module, choose M here: the
module will be called rz-mtu3-cnt.
config STM32_LPTIMER_CNT
tristate "STM32 LP Timer encoder counter driver"
depends on MFD_STM32_LPTIMER || COMPILE_TEST
......
......@@ -8,6 +8,7 @@ counter-y := counter-core.o counter-sysfs.o counter-chrdev.o
obj-$(CONFIG_104_QUAD_8) += 104-quad-8.o
obj-$(CONFIG_INTERRUPT_CNT) += interrupt-cnt.o
obj-$(CONFIG_RZ_MTU3_CNT) += rz-mtu3-cnt.o
obj-$(CONFIG_STM32_TIMER_CNT) += stm32-timer-cnt.o
obj-$(CONFIG_STM32_LPTIMER_CNT) += stm32-lptimer-cnt.o
obj-$(CONFIG_TI_EQEP) += ti-eqep.o
......
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas RZ/G2L MTU3a Counter driver
*
* Copyright (C) 2022 Renesas Electronics Corporation
*/
#include <linux/clk.h>
#include <linux/counter.h>
#include <linux/mfd/rz-mtu3.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/types.h>
/*
* Register descriptions
* TSR: Timer Status Register
* TMDR1: Timer Mode Register 1
* TMDR3: Timer Mode Register 3
* TIOR: Timer I/O Control Register
* TCR: Timer Control Register
* TCNT: Timer Counter
* TGRA: Timer general register A
* TCNTLW: Timer Longword Counter
* TGRALW: Timer longword general register A
*/
#define RZ_MTU3_TSR_TCFD BIT(7) /* Count Direction Flag */
#define RZ_MTU3_TMDR1_PH_CNT_MODE_1 (4) /* Phase counting mode 1 */
#define RZ_MTU3_TMDR1_PH_CNT_MODE_2 (5) /* Phase counting mode 2 */
#define RZ_MTU3_TMDR1_PH_CNT_MODE_3 (6) /* Phase counting mode 3 */
#define RZ_MTU3_TMDR1_PH_CNT_MODE_4 (7) /* Phase counting mode 4 */
#define RZ_MTU3_TMDR1_PH_CNT_MODE_5 (9) /* Phase counting mode 5 */
#define RZ_MTU3_TMDR1_PH_CNT_MODE_MASK (0xf)
/*
* LWA: MTU1/MTU2 Combination Longword Access Control
* 0: 16-bit, 1: 32-bit
*/
#define RZ_MTU3_TMDR3_LWA (0)
/*
* PHCKSEL: External Input Phase Clock Select
* 0: MTCLKA and MTCLKB, 1: MTCLKC and MTCLKD
*/
#define RZ_MTU3_TMDR3_PHCKSEL (1)
#define RZ_MTU3_16_BIT_MTU1_CH (0)
#define RZ_MTU3_16_BIT_MTU2_CH (1)
#define RZ_MTU3_32_BIT_CH (2)
#define RZ_MTU3_TIOR_NO_OUTPUT (0) /* Output prohibited */
#define RZ_MTU3_TIOR_IC_BOTH (10) /* Input capture at both edges */
#define SIGNAL_A_ID (0)
#define SIGNAL_B_ID (1)
#define SIGNAL_C_ID (2)
#define SIGNAL_D_ID (3)
#define RZ_MTU3_MAX_HW_CNTR_CHANNELS (2)
#define RZ_MTU3_MAX_LOGICAL_CNTR_CHANNELS (3)
/**
* struct rz_mtu3_cnt - MTU3 counter private data
*
* @clk: MTU3 module clock
* @lock: Lock to prevent concurrent access for ceiling and count
* @ch: HW channels for the counters
* @count_is_enabled: Enabled state of Counter value channel
* @mtu_16bit_max: Cache for 16-bit counters
* @mtu_32bit_max: Cache for 32-bit counters
*/
struct rz_mtu3_cnt {
struct clk *clk;
struct mutex lock;
struct rz_mtu3_channel *ch;
bool count_is_enabled[RZ_MTU3_MAX_LOGICAL_CNTR_CHANNELS];
union {
u16 mtu_16bit_max[RZ_MTU3_MAX_HW_CNTR_CHANNELS];
u32 mtu_32bit_max;
};
};
static const enum counter_function rz_mtu3_count_functions[] = {
COUNTER_FUNCTION_QUADRATURE_X4,
COUNTER_FUNCTION_PULSE_DIRECTION,
COUNTER_FUNCTION_QUADRATURE_X2_B,
};
static inline size_t rz_mtu3_get_hw_ch(const size_t id)
{
return (id == RZ_MTU3_32_BIT_CH) ? 0 : id;
}
static inline struct rz_mtu3_channel *rz_mtu3_get_ch(struct counter_device *counter, int id)
{
struct rz_mtu3_cnt *const priv = counter_priv(counter);
const size_t ch_id = rz_mtu3_get_hw_ch(id);
return &priv->ch[ch_id];
}
static bool rz_mtu3_is_counter_invalid(struct counter_device *counter, int id)
{
struct rz_mtu3_cnt *const priv = counter_priv(counter);
unsigned long tmdr;
pm_runtime_get_sync(priv->ch->dev);
tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
pm_runtime_put(priv->ch->dev);
if (id == RZ_MTU3_32_BIT_CH && test_bit(RZ_MTU3_TMDR3_LWA, &tmdr))
return false;
if (id != RZ_MTU3_32_BIT_CH && !test_bit(RZ_MTU3_TMDR3_LWA, &tmdr))
return false;
return true;
}
static int rz_mtu3_lock_if_counter_is_valid(struct counter_device *counter,
struct rz_mtu3_channel *const ch,
struct rz_mtu3_cnt *const priv,
int id)
{
mutex_lock(&priv->lock);
if (ch->is_busy && !priv->count_is_enabled[id]) {
mutex_unlock(&priv->lock);
return -EINVAL;
}
if (rz_mtu3_is_counter_invalid(counter, id)) {
mutex_unlock(&priv->lock);
return -EBUSY;
}
return 0;
}
static int rz_mtu3_lock_if_count_is_enabled(struct rz_mtu3_channel *const ch,
struct rz_mtu3_cnt *const priv,
int id)
{
mutex_lock(&priv->lock);
if (ch->is_busy && !priv->count_is_enabled[id]) {
mutex_unlock(&priv->lock);
return -EINVAL;
}
return 0;
}
static int rz_mtu3_count_read(struct counter_device *counter,
struct counter_count *count, u64 *val)
{
struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
struct rz_mtu3_cnt *const priv = counter_priv(counter);
int ret;
ret = rz_mtu3_lock_if_counter_is_valid(counter, ch, priv, count->id);
if (ret)
return ret;
pm_runtime_get_sync(ch->dev);
if (count->id == RZ_MTU3_32_BIT_CH)
*val = rz_mtu3_32bit_ch_read(ch, RZ_MTU3_TCNTLW);
else
*val = rz_mtu3_16bit_ch_read(ch, RZ_MTU3_TCNT);
pm_runtime_put(ch->dev);
mutex_unlock(&priv->lock);
return 0;
}
static int rz_mtu3_count_write(struct counter_device *counter,
struct counter_count *count, const u64 val)
{
struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
struct rz_mtu3_cnt *const priv = counter_priv(counter);
int ret;
ret = rz_mtu3_lock_if_counter_is_valid(counter, ch, priv, count->id);
if (ret)
return ret;
pm_runtime_get_sync(ch->dev);
if (count->id == RZ_MTU3_32_BIT_CH)
rz_mtu3_32bit_ch_write(ch, RZ_MTU3_TCNTLW, val);
else
rz_mtu3_16bit_ch_write(ch, RZ_MTU3_TCNT, val);
pm_runtime_put(ch->dev);
mutex_unlock(&priv->lock);
return 0;
}
static int rz_mtu3_count_function_read_helper(struct rz_mtu3_channel *const ch,
struct rz_mtu3_cnt *const priv,
enum counter_function *function)
{
u8 timer_mode;
pm_runtime_get_sync(ch->dev);
timer_mode = rz_mtu3_8bit_ch_read(ch, RZ_MTU3_TMDR1);
pm_runtime_put(ch->dev);
switch (timer_mode & RZ_MTU3_TMDR1_PH_CNT_MODE_MASK) {
case RZ_MTU3_TMDR1_PH_CNT_MODE_1:
*function = COUNTER_FUNCTION_QUADRATURE_X4;
return 0;
case RZ_MTU3_TMDR1_PH_CNT_MODE_2:
*function = COUNTER_FUNCTION_PULSE_DIRECTION;
return 0;
case RZ_MTU3_TMDR1_PH_CNT_MODE_4:
*function = COUNTER_FUNCTION_QUADRATURE_X2_B;
return 0;
default:
/*
* TODO:
* - need to add RZ_MTU3_TMDR1_PH_CNT_MODE_3
* - need to add RZ_MTU3_TMDR1_PH_CNT_MODE_5
*/
return -EINVAL;
}
}
static int rz_mtu3_count_function_read(struct counter_device *counter,
struct counter_count *count,
enum counter_function *function)
{
struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
struct rz_mtu3_cnt *const priv = counter_priv(counter);
int ret;
ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id);
if (ret)
return ret;
ret = rz_mtu3_count_function_read_helper(ch, priv, function);
mutex_unlock(&priv->lock);
return ret;
}
static int rz_mtu3_count_function_write(struct counter_device *counter,
struct counter_count *count,
enum counter_function function)
{
struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
struct rz_mtu3_cnt *const priv = counter_priv(counter);
u8 timer_mode;
int ret;
ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id);
if (ret)
return ret;
switch (function) {
case COUNTER_FUNCTION_QUADRATURE_X4:
timer_mode = RZ_MTU3_TMDR1_PH_CNT_MODE_1;
break;
case COUNTER_FUNCTION_PULSE_DIRECTION:
timer_mode = RZ_MTU3_TMDR1_PH_CNT_MODE_2;
break;
case COUNTER_FUNCTION_QUADRATURE_X2_B:
timer_mode = RZ_MTU3_TMDR1_PH_CNT_MODE_4;
break;
default:
/*
* TODO:
* - need to add RZ_MTU3_TMDR1_PH_CNT_MODE_3
* - need to add RZ_MTU3_TMDR1_PH_CNT_MODE_5
*/
mutex_unlock(&priv->lock);
return -EINVAL;
}
pm_runtime_get_sync(ch->dev);
rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TMDR1, timer_mode);
pm_runtime_put(ch->dev);
mutex_unlock(&priv->lock);
return 0;
}
static int rz_mtu3_count_direction_read(struct counter_device *counter,
struct counter_count *count,
enum counter_count_direction *direction)
{
struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
struct rz_mtu3_cnt *const priv = counter_priv(counter);
int ret;
u8 tsr;
ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id);
if (ret)
return ret;
pm_runtime_get_sync(ch->dev);
tsr = rz_mtu3_8bit_ch_read(ch, RZ_MTU3_TSR);
pm_runtime_put(ch->dev);
*direction = (tsr & RZ_MTU3_TSR_TCFD) ?
COUNTER_COUNT_DIRECTION_FORWARD : COUNTER_COUNT_DIRECTION_BACKWARD;
mutex_unlock(&priv->lock);
return 0;
}
static int rz_mtu3_count_ceiling_read(struct counter_device *counter,
struct counter_count *count,
u64 *ceiling)
{
struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
struct rz_mtu3_cnt *const priv = counter_priv(counter);
const size_t ch_id = rz_mtu3_get_hw_ch(count->id);
int ret;
ret = rz_mtu3_lock_if_counter_is_valid(counter, ch, priv, count->id);
if (ret)
return ret;
switch (count->id) {
case RZ_MTU3_16_BIT_MTU1_CH:
case RZ_MTU3_16_BIT_MTU2_CH:
*ceiling = priv->mtu_16bit_max[ch_id];
break;
case RZ_MTU3_32_BIT_CH:
*ceiling = priv->mtu_32bit_max;
break;
default:
/* should never reach this path */
mutex_unlock(&priv->lock);
return -EINVAL;
}
mutex_unlock(&priv->lock);
return 0;
}
static int rz_mtu3_count_ceiling_write(struct counter_device *counter,
struct counter_count *count,
u64 ceiling)
{
struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
struct rz_mtu3_cnt *const priv = counter_priv(counter);
const size_t ch_id = rz_mtu3_get_hw_ch(count->id);
int ret;
ret = rz_mtu3_lock_if_counter_is_valid(counter, ch, priv, count->id);
if (ret)
return ret;
switch (count->id) {
case RZ_MTU3_16_BIT_MTU1_CH:
case RZ_MTU3_16_BIT_MTU2_CH:
if (ceiling > U16_MAX) {
mutex_unlock(&priv->lock);
return -ERANGE;
}
priv->mtu_16bit_max[ch_id] = ceiling;
break;
case RZ_MTU3_32_BIT_CH:
if (ceiling > U32_MAX) {
mutex_unlock(&priv->lock);
return -ERANGE;
}
priv->mtu_32bit_max = ceiling;
break;
default:
/* should never reach this path */
mutex_unlock(&priv->lock);
return -EINVAL;
}
pm_runtime_get_sync(ch->dev);
if (count->id == RZ_MTU3_32_BIT_CH)
rz_mtu3_32bit_ch_write(ch, RZ_MTU3_TGRALW, ceiling);
else
rz_mtu3_16bit_ch_write(ch, RZ_MTU3_TGRA, ceiling);
rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TCR, RZ_MTU3_TCR_CCLR_TGRA);
pm_runtime_put(ch->dev);
mutex_unlock(&priv->lock);
return 0;
}
static void rz_mtu3_32bit_cnt_setting(struct counter_device *counter)
{
struct rz_mtu3_channel *const ch1 = rz_mtu3_get_ch(counter, 0);
struct rz_mtu3_channel *const ch2 = rz_mtu3_get_ch(counter, 1);
/* Phase counting mode 1 is used as default in initialization. */
rz_mtu3_8bit_ch_write(ch1, RZ_MTU3_TMDR1, RZ_MTU3_TMDR1_PH_CNT_MODE_1);
rz_mtu3_8bit_ch_write(ch1, RZ_MTU3_TCR, RZ_MTU3_TCR_CCLR_TGRA);
rz_mtu3_8bit_ch_write(ch1, RZ_MTU3_TIOR, RZ_MTU3_TIOR_IC_BOTH);
rz_mtu3_enable(ch1);
rz_mtu3_enable(ch2);
}
static void rz_mtu3_16bit_cnt_setting(struct counter_device *counter, int id)
{
struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, id);
/* Phase counting mode 1 is used as default in initialization. */
rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TMDR1, RZ_MTU3_TMDR1_PH_CNT_MODE_1);
rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TCR, RZ_MTU3_TCR_CCLR_TGRA);
rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TIOR, RZ_MTU3_TIOR_NO_OUTPUT);
rz_mtu3_enable(ch);
}
static int rz_mtu3_initialize_counter(struct counter_device *counter, int id)
{
struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, id);
struct rz_mtu3_channel *const ch1 = rz_mtu3_get_ch(counter, 0);
struct rz_mtu3_channel *const ch2 = rz_mtu3_get_ch(counter, 1);
switch (id) {
case RZ_MTU3_16_BIT_MTU1_CH:
case RZ_MTU3_16_BIT_MTU2_CH:
if (!rz_mtu3_request_channel(ch))
return -EBUSY;
rz_mtu3_16bit_cnt_setting(counter, id);
return 0;
case RZ_MTU3_32_BIT_CH:
/*
* 32-bit phase counting need MTU1 and MTU2 to create 32-bit
* cascade counter.
*/
if (!rz_mtu3_request_channel(ch1))
return -EBUSY;
if (!rz_mtu3_request_channel(ch2)) {
rz_mtu3_release_channel(ch1);
return -EBUSY;
}
rz_mtu3_32bit_cnt_setting(counter);
return 0;
default:
/* should never reach this path */
return -EINVAL;
}
}
static void rz_mtu3_terminate_counter(struct counter_device *counter, int id)
{
struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, id);
struct rz_mtu3_channel *const ch1 = rz_mtu3_get_ch(counter, 0);
struct rz_mtu3_channel *const ch2 = rz_mtu3_get_ch(counter, 1);
if (id == RZ_MTU3_32_BIT_CH) {
rz_mtu3_release_channel(ch2);
rz_mtu3_release_channel(ch1);
rz_mtu3_disable(ch2);
rz_mtu3_disable(ch1);
} else {
rz_mtu3_release_channel(ch);
rz_mtu3_disable(ch);
}
}
static int rz_mtu3_count_enable_read(struct counter_device *counter,
struct counter_count *count, u8 *enable)
{
struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
struct rz_mtu3_channel *const ch1 = rz_mtu3_get_ch(counter, 0);
struct rz_mtu3_channel *const ch2 = rz_mtu3_get_ch(counter, 1);
struct rz_mtu3_cnt *const priv = counter_priv(counter);
int ret;
ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id);
if (ret)
return ret;
if (count->id == RZ_MTU3_32_BIT_CH)
*enable = rz_mtu3_is_enabled(ch1) && rz_mtu3_is_enabled(ch2);
else
*enable = rz_mtu3_is_enabled(ch);
mutex_unlock(&priv->lock);
return 0;
}
static int rz_mtu3_count_enable_write(struct counter_device *counter,
struct counter_count *count, u8 enable)
{
struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
struct rz_mtu3_cnt *const priv = counter_priv(counter);
int ret = 0;
if (enable) {
pm_runtime_get_sync(ch->dev);
mutex_lock(&priv->lock);
ret = rz_mtu3_initialize_counter(counter, count->id);
if (ret == 0)
priv->count_is_enabled[count->id] = true;
mutex_unlock(&priv->lock);
} else {
mutex_lock(&priv->lock);
rz_mtu3_terminate_counter(counter, count->id);
priv->count_is_enabled[count->id] = false;
mutex_unlock(&priv->lock);
pm_runtime_put(ch->dev);
}
return ret;
}
static int rz_mtu3_lock_if_ch0_is_enabled(struct rz_mtu3_cnt *const priv)
{
mutex_lock(&priv->lock);
if (priv->ch->is_busy && !(priv->count_is_enabled[RZ_MTU3_16_BIT_MTU1_CH] ||
priv->count_is_enabled[RZ_MTU3_32_BIT_CH])) {
mutex_unlock(&priv->lock);
return -EINVAL;
}
return 0;
}
static int rz_mtu3_cascade_counts_enable_get(struct counter_device *counter,
u8 *cascade_enable)
{
struct rz_mtu3_cnt *const priv = counter_priv(counter);
unsigned long tmdr;
int ret;
ret = rz_mtu3_lock_if_ch0_is_enabled(priv);
if (ret)
return ret;
pm_runtime_get_sync(priv->ch->dev);
tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
pm_runtime_put(priv->ch->dev);
*cascade_enable = test_bit(RZ_MTU3_TMDR3_LWA, &tmdr);
mutex_unlock(&priv->lock);
return 0;
}
static int rz_mtu3_cascade_counts_enable_set(struct counter_device *counter,
u8 cascade_enable)
{
struct rz_mtu3_cnt *const priv = counter_priv(counter);
int ret;
ret = rz_mtu3_lock_if_ch0_is_enabled(priv);
if (ret)
return ret;
pm_runtime_get_sync(priv->ch->dev);
rz_mtu3_shared_reg_update_bit(priv->ch, RZ_MTU3_TMDR3,
RZ_MTU3_TMDR3_LWA, cascade_enable);
pm_runtime_put(priv->ch->dev);
mutex_unlock(&priv->lock);
return 0;
}
static int rz_mtu3_ext_input_phase_clock_select_get(struct counter_device *counter,
u32 *ext_input_phase_clock_select)
{
struct rz_mtu3_cnt *const priv = counter_priv(counter);
unsigned long tmdr;
int ret;
ret = rz_mtu3_lock_if_ch0_is_enabled(priv);
if (ret)
return ret;
pm_runtime_get_sync(priv->ch->dev);
tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
pm_runtime_put(priv->ch->dev);
*ext_input_phase_clock_select = test_bit(RZ_MTU3_TMDR3_PHCKSEL, &tmdr);
mutex_unlock(&priv->lock);
return 0;
}
static int rz_mtu3_ext_input_phase_clock_select_set(struct counter_device *counter,
u32 ext_input_phase_clock_select)
{
struct rz_mtu3_cnt *const priv = counter_priv(counter);
int ret;
ret = rz_mtu3_lock_if_ch0_is_enabled(priv);
if (ret)
return ret;
pm_runtime_get_sync(priv->ch->dev);
rz_mtu3_shared_reg_update_bit(priv->ch, RZ_MTU3_TMDR3,
RZ_MTU3_TMDR3_PHCKSEL,
ext_input_phase_clock_select);
pm_runtime_put(priv->ch->dev);
mutex_unlock(&priv->lock);
return 0;
}
static struct counter_comp rz_mtu3_count_ext[] = {
COUNTER_COMP_DIRECTION(rz_mtu3_count_direction_read),
COUNTER_COMP_ENABLE(rz_mtu3_count_enable_read,
rz_mtu3_count_enable_write),
COUNTER_COMP_CEILING(rz_mtu3_count_ceiling_read,
rz_mtu3_count_ceiling_write),
};
static const enum counter_synapse_action rz_mtu3_synapse_actions[] = {
COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
COUNTER_SYNAPSE_ACTION_RISING_EDGE,
COUNTER_SYNAPSE_ACTION_NONE,
};
static int rz_mtu3_action_read(struct counter_device *counter,
struct counter_count *count,
struct counter_synapse *synapse,
enum counter_synapse_action *action)
{
const bool is_signal_ab = (synapse->signal->id == SIGNAL_A_ID) ||
(synapse->signal->id == SIGNAL_B_ID);
struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
struct rz_mtu3_cnt *const priv = counter_priv(counter);
enum counter_function function;
bool mtclkc_mtclkd;
unsigned long tmdr;
int ret;
ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id);
if (ret)
return ret;
ret = rz_mtu3_count_function_read_helper(ch, priv, &function);
if (ret) {
mutex_unlock(&priv->lock);
return ret;
}
/* Default action mode */
*action = COUNTER_SYNAPSE_ACTION_NONE;
if (count->id != RZ_MTU3_16_BIT_MTU1_CH) {
tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
mtclkc_mtclkd = test_bit(RZ_MTU3_TMDR3_PHCKSEL, &tmdr);
if ((mtclkc_mtclkd && is_signal_ab) ||
(!mtclkc_mtclkd && !is_signal_ab)) {
mutex_unlock(&priv->lock);
return 0;
}
}
switch (function) {
case COUNTER_FUNCTION_PULSE_DIRECTION:
/*
* Rising edges on signal A (signal C) updates the respective
* count. The input level of signal B (signal D) determines
* direction.
*/
if (synapse->signal->id == SIGNAL_A_ID ||
synapse->signal->id == SIGNAL_C_ID)
*action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
break;
case COUNTER_FUNCTION_QUADRATURE_X2_B:
/*
* Any state transition on quadrature pair signal B (signal D)
* updates the respective count.
*/
if (synapse->signal->id == SIGNAL_B_ID ||
synapse->signal->id == SIGNAL_D_ID)
*action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
break;
case COUNTER_FUNCTION_QUADRATURE_X4:
/* counts up/down on both edges of A (C) and B (D) signal */
*action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
break;
default:
/* should never reach this path */
mutex_unlock(&priv->lock);
return -EINVAL;
}
mutex_unlock(&priv->lock);
return 0;
}
static const struct counter_ops rz_mtu3_cnt_ops = {
.count_read = rz_mtu3_count_read,
.count_write = rz_mtu3_count_write,
.function_read = rz_mtu3_count_function_read,
.function_write = rz_mtu3_count_function_write,
.action_read = rz_mtu3_action_read,
};
#define RZ_MTU3_PHASE_SIGNAL(_id, _name) { \
.id = (_id), \
.name = (_name), \
}
static struct counter_signal rz_mtu3_signals[] = {
RZ_MTU3_PHASE_SIGNAL(SIGNAL_A_ID, "MTU1 MTCLKA"),
RZ_MTU3_PHASE_SIGNAL(SIGNAL_B_ID, "MTU1 MTCLKB"),
RZ_MTU3_PHASE_SIGNAL(SIGNAL_C_ID, "MTU2 MTCLKC"),
RZ_MTU3_PHASE_SIGNAL(SIGNAL_D_ID, "MTU2 MTCLKD"),
};
static struct counter_synapse rz_mtu3_mtu1_count_synapses[] = {
{
.actions_list = rz_mtu3_synapse_actions,
.num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
.signal = rz_mtu3_signals,
},
{
.actions_list = rz_mtu3_synapse_actions,
.num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
.signal = rz_mtu3_signals + 1,
}
};
static struct counter_synapse rz_mtu3_mtu2_count_synapses[] = {
{
.actions_list = rz_mtu3_synapse_actions,
.num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
.signal = rz_mtu3_signals,
},
{
.actions_list = rz_mtu3_synapse_actions,
.num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
.signal = rz_mtu3_signals + 1,
},
{
.actions_list = rz_mtu3_synapse_actions,
.num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
.signal = rz_mtu3_signals + 2,
},
{
.actions_list = rz_mtu3_synapse_actions,
.num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
.signal = rz_mtu3_signals + 3,
}
};
static struct counter_count rz_mtu3_counts[] = {
{
.id = RZ_MTU3_16_BIT_MTU1_CH,
.name = "Channel 1 Count",
.functions_list = rz_mtu3_count_functions,
.num_functions = ARRAY_SIZE(rz_mtu3_count_functions),
.synapses = rz_mtu3_mtu1_count_synapses,
.num_synapses = ARRAY_SIZE(rz_mtu3_mtu1_count_synapses),
.ext = rz_mtu3_count_ext,
.num_ext = ARRAY_SIZE(rz_mtu3_count_ext),
},
{
.id = RZ_MTU3_16_BIT_MTU2_CH,
.name = "Channel 2 Count",
.functions_list = rz_mtu3_count_functions,
.num_functions = ARRAY_SIZE(rz_mtu3_count_functions),
.synapses = rz_mtu3_mtu2_count_synapses,
.num_synapses = ARRAY_SIZE(rz_mtu3_mtu2_count_synapses),
.ext = rz_mtu3_count_ext,
.num_ext = ARRAY_SIZE(rz_mtu3_count_ext),
},
{
.id = RZ_MTU3_32_BIT_CH,
.name = "Channel 1 and 2 (cascaded) Count",
.functions_list = rz_mtu3_count_functions,
.num_functions = ARRAY_SIZE(rz_mtu3_count_functions),
.synapses = rz_mtu3_mtu2_count_synapses,
.num_synapses = ARRAY_SIZE(rz_mtu3_mtu2_count_synapses),
.ext = rz_mtu3_count_ext,
.num_ext = ARRAY_SIZE(rz_mtu3_count_ext),
}
};
static const char *const rz_mtu3_ext_input_phase_clock_select[] = {
"MTCLKA-MTCLKB",
"MTCLKC-MTCLKD",
};
static DEFINE_COUNTER_ENUM(rz_mtu3_ext_input_phase_clock_select_enum,
rz_mtu3_ext_input_phase_clock_select);
static struct counter_comp rz_mtu3_device_ext[] = {
COUNTER_COMP_DEVICE_BOOL("cascade_counts_enable",
rz_mtu3_cascade_counts_enable_get,
rz_mtu3_cascade_counts_enable_set),
COUNTER_COMP_DEVICE_ENUM("external_input_phase_clock_select",
rz_mtu3_ext_input_phase_clock_select_get,
rz_mtu3_ext_input_phase_clock_select_set,
rz_mtu3_ext_input_phase_clock_select_enum),
};
static int rz_mtu3_cnt_pm_runtime_suspend(struct device *dev)
{
struct clk *const clk = dev_get_drvdata(dev);
clk_disable_unprepare(clk);
return 0;
}
static int rz_mtu3_cnt_pm_runtime_resume(struct device *dev)
{
struct clk *const clk = dev_get_drvdata(dev);
clk_prepare_enable(clk);
return 0;
}
static DEFINE_RUNTIME_DEV_PM_OPS(rz_mtu3_cnt_pm_ops,
rz_mtu3_cnt_pm_runtime_suspend,
rz_mtu3_cnt_pm_runtime_resume, NULL);
static void rz_mtu3_cnt_pm_disable(void *data)
{
struct device *dev = data;
pm_runtime_disable(dev);
pm_runtime_set_suspended(dev);
}
static int rz_mtu3_cnt_probe(struct platform_device *pdev)
{
struct rz_mtu3 *ddata = dev_get_drvdata(pdev->dev.parent);
struct device *dev = &pdev->dev;
struct counter_device *counter;
struct rz_mtu3_channel *ch;
struct rz_mtu3_cnt *priv;
unsigned int i;
int ret;
counter = devm_counter_alloc(dev, sizeof(*priv));
if (!counter)
return -ENOMEM;
priv = counter_priv(counter);
priv->clk = ddata->clk;
priv->mtu_32bit_max = U32_MAX;
priv->ch = &ddata->channels[RZ_MTU3_CHAN_1];
ch = &priv->ch[0];
for (i = 0; i < RZ_MTU3_MAX_HW_CNTR_CHANNELS; i++) {
ch->dev = dev;
priv->mtu_16bit_max[i] = U16_MAX;
ch++;
}
mutex_init(&priv->lock);
platform_set_drvdata(pdev, priv->clk);
clk_prepare_enable(priv->clk);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
ret = devm_add_action_or_reset(&pdev->dev, rz_mtu3_cnt_pm_disable, dev);
if (ret < 0)
goto disable_clock;
counter->name = dev_name(dev);
counter->parent = dev;
counter->ops = &rz_mtu3_cnt_ops;
counter->counts = rz_mtu3_counts;
counter->num_counts = ARRAY_SIZE(rz_mtu3_counts);
counter->signals = rz_mtu3_signals;
counter->num_signals = ARRAY_SIZE(rz_mtu3_signals);
counter->ext = rz_mtu3_device_ext;
counter->num_ext = ARRAY_SIZE(rz_mtu3_device_ext);
/* Register Counter device */
ret = devm_counter_add(dev, counter);
if (ret < 0) {
dev_err_probe(dev, ret, "Failed to add counter\n");
goto disable_clock;
}
return 0;
disable_clock:
clk_disable_unprepare(priv->clk);
return ret;
}
static struct platform_driver rz_mtu3_cnt_driver = {
.probe = rz_mtu3_cnt_probe,
.driver = {
.name = "rz-mtu3-counter",
.pm = pm_ptr(&rz_mtu3_cnt_pm_ops),
},
};
module_platform_driver(rz_mtu3_cnt_driver);
MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
MODULE_ALIAS("platform:rz-mtu3-counter");
MODULE_DESCRIPTION("Renesas RZ/G2L MTU3a counter driver");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(COUNTER);
......@@ -1292,6 +1292,18 @@ config GPIO_KEMPLD
This driver can also be built as a module. If so, the module will be
called gpio-kempld.
config GPIO_LJCA
tristate "INTEL La Jolla Cove Adapter GPIO support"
depends on MFD_LJCA
select GPIOLIB_IRQCHIP
default MFD_LJCA
help
Select this option to enable GPIO driver for the INTEL
La Jolla Cove Adapter (LJCA) board.
This driver can also be built as a module. If so, the module
will be called gpio-ljca.
config GPIO_LP3943
tristate "TI/National Semiconductor LP3943 GPIO expander"
depends on MFD_LP3943
......
......@@ -79,6 +79,7 @@ obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o
obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o
obj-$(CONFIG_GPIO_LATCH) += gpio-latch.o
obj-$(CONFIG_GPIO_LJCA) += gpio-ljca.o
obj-$(CONFIG_GPIO_LOGICVC) += gpio-logicvc.o
obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o
obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* Intel La Jolla Cove Adapter USB-GPIO driver
*
* Copyright (c) 2023, Intel Corporation.
*/
#include <linux/acpi.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/dev_printk.h>
#include <linux/gpio/driver.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/kref.h>
#include <linux/mfd/ljca.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/types.h>
/* GPIO commands */
#define LJCA_GPIO_CONFIG 1
#define LJCA_GPIO_READ 2
#define LJCA_GPIO_WRITE 3
#define LJCA_GPIO_INT_EVENT 4
#define LJCA_GPIO_INT_MASK 5
#define LJCA_GPIO_INT_UNMASK 6
#define LJCA_GPIO_CONF_DISABLE BIT(0)
#define LJCA_GPIO_CONF_INPUT BIT(1)
#define LJCA_GPIO_CONF_OUTPUT BIT(2)
#define LJCA_GPIO_CONF_PULLUP BIT(3)
#define LJCA_GPIO_CONF_PULLDOWN BIT(4)
#define LJCA_GPIO_CONF_DEFAULT BIT(5)
#define LJCA_GPIO_CONF_INTERRUPT BIT(6)
#define LJCA_GPIO_INT_TYPE BIT(7)
#define LJCA_GPIO_CONF_EDGE FIELD_PREP(LJCA_GPIO_INT_TYPE, 1)
#define LJCA_GPIO_CONF_LEVEL FIELD_PREP(LJCA_GPIO_INT_TYPE, 0)
/* Intentional overlap with PULLUP / PULLDOWN */
#define LJCA_GPIO_CONF_SET BIT(3)
#define LJCA_GPIO_CONF_CLR BIT(4)
struct gpio_op {
u8 index;
u8 value;
} __packed;
struct gpio_packet {
u8 num;
struct gpio_op item[];
} __packed;
#define LJCA_GPIO_BUF_SIZE 60
struct ljca_gpio_dev {
struct platform_device *pdev;
struct gpio_chip gc;
struct ljca_gpio_info *gpio_info;
DECLARE_BITMAP(unmasked_irqs, LJCA_MAX_GPIO_NUM);
DECLARE_BITMAP(enabled_irqs, LJCA_MAX_GPIO_NUM);
DECLARE_BITMAP(reenable_irqs, LJCA_MAX_GPIO_NUM);
u8 *connect_mode;
/* mutex to protect irq bus */
struct mutex irq_lock;
struct work_struct work;
/* lock to protect package transfer to Hardware */
struct mutex trans_lock;
u8 obuf[LJCA_GPIO_BUF_SIZE];
u8 ibuf[LJCA_GPIO_BUF_SIZE];
};
static int gpio_config(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id, u8 config)
{
struct gpio_packet *packet = (struct gpio_packet *)ljca_gpio->obuf;
int ret;
mutex_lock(&ljca_gpio->trans_lock);
packet->item[0].index = gpio_id;
packet->item[0].value = config | ljca_gpio->connect_mode[gpio_id];
packet->num = 1;
ret = ljca_transfer(ljca_gpio->gpio_info->ljca, LJCA_GPIO_CONFIG, packet,
struct_size(packet, item, packet->num), NULL, NULL);
mutex_unlock(&ljca_gpio->trans_lock);
return ret;
}
static int ljca_gpio_read(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id)
{
struct gpio_packet *packet = (struct gpio_packet *)ljca_gpio->obuf;
struct gpio_packet *ack_packet = (struct gpio_packet *)ljca_gpio->ibuf;
unsigned int ibuf_len = LJCA_GPIO_BUF_SIZE;
int ret;
mutex_lock(&ljca_gpio->trans_lock);
packet->num = 1;
packet->item[0].index = gpio_id;
ret = ljca_transfer(ljca_gpio->gpio_info->ljca, LJCA_GPIO_READ, packet,
struct_size(packet, item, packet->num), ljca_gpio->ibuf, &ibuf_len);
if (ret)
goto out_unlock;
if (!ibuf_len || ack_packet->num != packet->num) {
dev_err(&ljca_gpio->pdev->dev, "failed gpio_id:%u %u", gpio_id, ack_packet->num);
ret = -EIO;
}
out_unlock:
mutex_unlock(&ljca_gpio->trans_lock);
if (ret)
return ret;
return ack_packet->item[0].value > 0;
}
static int ljca_gpio_write(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id,
int value)
{
struct gpio_packet *packet = (struct gpio_packet *)ljca_gpio->obuf;
int ret;
mutex_lock(&ljca_gpio->trans_lock);
packet->num = 1;
packet->item[0].index = gpio_id;
packet->item[0].value = value & 1;
ret = ljca_transfer(ljca_gpio->gpio_info->ljca, LJCA_GPIO_WRITE, packet,
struct_size(packet, item, packet->num), NULL, NULL);
mutex_unlock(&ljca_gpio->trans_lock);
return ret;
}
static int ljca_gpio_get_value(struct gpio_chip *chip, unsigned int offset)
{
struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip);
return ljca_gpio_read(ljca_gpio, offset);
}
static void ljca_gpio_set_value(struct gpio_chip *chip, unsigned int offset,
int val)
{
struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip);
int ret;
ret = ljca_gpio_write(ljca_gpio, offset, val);
if (ret)
dev_err(chip->parent, "offset:%u val:%d set value failed %d\n", offset, val, ret);
}
static int ljca_gpio_direction_input(struct gpio_chip *chip,
unsigned int offset)
{
struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip);
u8 config = LJCA_GPIO_CONF_INPUT | LJCA_GPIO_CONF_CLR;
return gpio_config(ljca_gpio, offset, config);
}
static int ljca_gpio_direction_output(struct gpio_chip *chip,
unsigned int offset, int val)
{
struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip);
u8 config = LJCA_GPIO_CONF_OUTPUT | LJCA_GPIO_CONF_CLR;
int ret;
ret = gpio_config(ljca_gpio, offset, config);
if (ret)
return ret;
ljca_gpio_set_value(chip, offset, val);
return 0;
}
static int ljca_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned long config)
{
struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip);
ljca_gpio->connect_mode[offset] = 0;
switch (pinconf_to_config_param(config)) {
case PIN_CONFIG_BIAS_PULL_UP:
ljca_gpio->connect_mode[offset] |= LJCA_GPIO_CONF_PULLUP;
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
ljca_gpio->connect_mode[offset] |= LJCA_GPIO_CONF_PULLDOWN;
break;
case PIN_CONFIG_DRIVE_PUSH_PULL:
case PIN_CONFIG_PERSIST_STATE:
break;
default:
return -ENOTSUPP;
}
return 0;
}
static int ljca_gpio_init_valid_mask(struct gpio_chip *chip, unsigned long *valid_mask,
unsigned int ngpios)
{
struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip);
WARN_ON_ONCE(ngpios != ljca_gpio->gpio_info->num);
bitmap_copy(valid_mask, ljca_gpio->gpio_info->valid_pin_map, ngpios);
return 0;
}
static void ljca_gpio_irq_init_valid_mask(struct gpio_chip *chip, unsigned long *valid_mask,
unsigned int ngpios)
{
ljca_gpio_init_valid_mask(chip, valid_mask, ngpios);
}
static int ljca_enable_irq(struct ljca_gpio_dev *ljca_gpio, int gpio_id, bool enable)
{
struct gpio_packet *packet = (struct gpio_packet *)ljca_gpio->obuf;
int ret;
mutex_lock(&ljca_gpio->trans_lock);
packet->num = 1;
packet->item[0].index = gpio_id;
packet->item[0].value = 0;
ret = ljca_transfer(ljca_gpio->gpio_info->ljca,
enable ? LJCA_GPIO_INT_UNMASK : LJCA_GPIO_INT_MASK, packet,
struct_size(packet, item, packet->num), NULL, NULL);
mutex_unlock(&ljca_gpio->trans_lock);
return ret;
}
static void ljca_gpio_async(struct work_struct *work)
{
struct ljca_gpio_dev *ljca_gpio = container_of(work, struct ljca_gpio_dev, work);
int gpio_id;
int unmasked;
for_each_set_bit(gpio_id, ljca_gpio->reenable_irqs, ljca_gpio->gc.ngpio) {
clear_bit(gpio_id, ljca_gpio->reenable_irqs);
unmasked = test_bit(gpio_id, ljca_gpio->unmasked_irqs);
if (unmasked)
ljca_enable_irq(ljca_gpio, gpio_id, true);
}
}
static void ljca_gpio_event_cb(void *context, u8 cmd, const void *evt_data, int len)
{
const struct gpio_packet *packet = evt_data;
struct ljca_gpio_dev *ljca_gpio = context;
int i;
int irq;
if (cmd != LJCA_GPIO_INT_EVENT)
return;
for (i = 0; i < packet->num; i++) {
irq = irq_find_mapping(ljca_gpio->gc.irq.domain, packet->item[i].index);
if (!irq) {
dev_err(ljca_gpio->gc.parent, "gpio_id %u does not mapped to IRQ yet\n",
packet->item[i].index);
return;
}
generic_handle_domain_irq(ljca_gpio->gc.irq.domain, irq);
set_bit(packet->item[i].index, ljca_gpio->reenable_irqs);
}
schedule_work(&ljca_gpio->work);
}
static void ljca_irq_unmask(struct irq_data *irqd)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(gc);
int gpio_id = irqd_to_hwirq(irqd);
gpiochip_enable_irq(gc, gpio_id);
set_bit(gpio_id, ljca_gpio->unmasked_irqs);
}
static void ljca_irq_mask(struct irq_data *irqd)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(gc);
int gpio_id = irqd_to_hwirq(irqd);
clear_bit(gpio_id, ljca_gpio->unmasked_irqs);
gpiochip_disable_irq(gc, gpio_id);
}
static int ljca_irq_set_type(struct irq_data *irqd, unsigned int type)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(gc);
int gpio_id = irqd_to_hwirq(irqd);
ljca_gpio->connect_mode[gpio_id] = LJCA_GPIO_CONF_INTERRUPT;
switch (type) {
case IRQ_TYPE_LEVEL_HIGH:
ljca_gpio->connect_mode[gpio_id] |= (LJCA_GPIO_CONF_LEVEL | LJCA_GPIO_CONF_PULLUP);
break;
case IRQ_TYPE_LEVEL_LOW:
ljca_gpio->connect_mode[gpio_id] |= (LJCA_GPIO_CONF_LEVEL | LJCA_GPIO_CONF_PULLDOWN);
break;
case IRQ_TYPE_EDGE_BOTH:
break;
case IRQ_TYPE_EDGE_RISING:
ljca_gpio->connect_mode[gpio_id] |= (LJCA_GPIO_CONF_EDGE | LJCA_GPIO_CONF_PULLUP);
break;
case IRQ_TYPE_EDGE_FALLING:
ljca_gpio->connect_mode[gpio_id] |= (LJCA_GPIO_CONF_EDGE | LJCA_GPIO_CONF_PULLDOWN);
break;
default:
return -EINVAL;
}
return 0;
}
static void ljca_irq_bus_lock(struct irq_data *irqd)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(gc);
mutex_lock(&ljca_gpio->irq_lock);
}
static void ljca_irq_bus_unlock(struct irq_data *irqd)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(gc);
int gpio_id = irqd_to_hwirq(irqd);
int enabled;
int unmasked;
enabled = test_bit(gpio_id, ljca_gpio->enabled_irqs);
unmasked = test_bit(gpio_id, ljca_gpio->unmasked_irqs);
if (enabled != unmasked) {
if (unmasked) {
gpio_config(ljca_gpio, gpio_id, 0);
ljca_enable_irq(ljca_gpio, gpio_id, true);
set_bit(gpio_id, ljca_gpio->enabled_irqs);
} else {
ljca_enable_irq(ljca_gpio, gpio_id, false);
clear_bit(gpio_id, ljca_gpio->enabled_irqs);
}
}
mutex_unlock(&ljca_gpio->irq_lock);
}
static const struct irq_chip ljca_gpio_irqchip = {
.name = "ljca-irq",
.irq_mask = ljca_irq_mask,
.irq_unmask = ljca_irq_unmask,
.irq_set_type = ljca_irq_set_type,
.irq_bus_lock = ljca_irq_bus_lock,
.irq_bus_sync_unlock = ljca_irq_bus_unlock,
.flags = IRQCHIP_IMMUTABLE,
GPIOCHIP_IRQ_RESOURCE_HELPERS,
};
static int ljca_gpio_probe(struct platform_device *pdev)
{
struct ljca_gpio_dev *ljca_gpio;
struct gpio_irq_chip *girq;
int ret;
ljca_gpio = devm_kzalloc(&pdev->dev, sizeof(*ljca_gpio), GFP_KERNEL);
if (!ljca_gpio)
return -ENOMEM;
ljca_gpio->gpio_info = dev_get_platdata(&pdev->dev);
ljca_gpio->connect_mode = devm_kcalloc(&pdev->dev, ljca_gpio->gpio_info->num,
sizeof(*ljca_gpio->connect_mode), GFP_KERNEL);
if (!ljca_gpio->connect_mode)
return -ENOMEM;
mutex_init(&ljca_gpio->irq_lock);
mutex_init(&ljca_gpio->trans_lock);
ljca_gpio->pdev = pdev;
ljca_gpio->gc.direction_input = ljca_gpio_direction_input;
ljca_gpio->gc.direction_output = ljca_gpio_direction_output;
ljca_gpio->gc.get = ljca_gpio_get_value;
ljca_gpio->gc.set = ljca_gpio_set_value;
ljca_gpio->gc.set_config = ljca_gpio_set_config;
ljca_gpio->gc.init_valid_mask = ljca_gpio_init_valid_mask;
ljca_gpio->gc.can_sleep = true;
ljca_gpio->gc.parent = &pdev->dev;
ljca_gpio->gc.base = -1;
ljca_gpio->gc.ngpio = ljca_gpio->gpio_info->num;
ljca_gpio->gc.label = ACPI_COMPANION(&pdev->dev) ?
acpi_dev_name(ACPI_COMPANION(&pdev->dev)) :
dev_name(&pdev->dev);
ljca_gpio->gc.owner = THIS_MODULE;
platform_set_drvdata(pdev, ljca_gpio);
ljca_register_event_cb(ljca_gpio->gpio_info->ljca, ljca_gpio_event_cb, ljca_gpio);
girq = &ljca_gpio->gc.irq;
gpio_irq_chip_set_chip(girq, &ljca_gpio_irqchip);
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_simple_irq;
girq->init_valid_mask = ljca_gpio_irq_init_valid_mask;
INIT_WORK(&ljca_gpio->work, ljca_gpio_async);
ret = gpiochip_add_data(&ljca_gpio->gc, ljca_gpio);
if (ret) {
ljca_unregister_event_cb(ljca_gpio->gpio_info->ljca);
mutex_destroy(&ljca_gpio->irq_lock);
mutex_destroy(&ljca_gpio->trans_lock);
}
return ret;
}
static int ljca_gpio_remove(struct platform_device *pdev)
{
struct ljca_gpio_dev *ljca_gpio = platform_get_drvdata(pdev);
gpiochip_remove(&ljca_gpio->gc);
ljca_unregister_event_cb(ljca_gpio->gpio_info->ljca);
mutex_destroy(&ljca_gpio->irq_lock);
mutex_destroy(&ljca_gpio->trans_lock);
return 0;
}
#define LJCA_GPIO_DRV_NAME "ljca-gpio"
static const struct platform_device_id ljca_gpio_id[] = {
{ LJCA_GPIO_DRV_NAME, 0 },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, ljca_gpio_id);
static struct platform_driver ljca_gpio_driver = {
.driver.name = LJCA_GPIO_DRV_NAME,
.probe = ljca_gpio_probe,
.remove = ljca_gpio_remove,
};
module_platform_driver(ljca_gpio_driver);
MODULE_AUTHOR("Ye Xiang <xiang.ye@intel.com>");
MODULE_AUTHOR("Wang Zhifeng <zhifeng.wang@intel.com>");
MODULE_AUTHOR("Zhang Lixu <lixu.zhang@intel.com>");
MODULE_DESCRIPTION("Intel La Jolla Cove Adapter USB-GPIO driver");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(LJCA);
......@@ -1117,8 +1117,7 @@ static int pm860x_dt_init(struct device_node *np,
{
int ret;
if (of_get_property(np, "marvell,88pm860x-irq-read-clr", NULL))
pdata->irq_mode = 1;
pdata->irq_mode = of_property_read_bool(np, "marvell,88pm860x-irq-read-clr");
ret = of_property_read_u32(np, "marvell,88pm860x-slave-addr",
&pdata->companion_addr);
if (ret) {
......@@ -1276,4 +1275,3 @@ module_exit(pm860x_i2c_exit);
MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x");
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
MODULE_LICENSE("GPL");
......@@ -266,6 +266,16 @@ config MFD_MADERA_SPI
Support for the Cirrus Logic Madera platform audio SoC
core functionality controlled via SPI.
config MFD_MAX597X
tristate "Maxim 597x power switch and monitor"
depends on (I2C && OF)
select MFD_SIMPLE_MFD_I2C
help
This driver controls a Maxim 5970/5978 switch via I2C bus.
The MAX5970/5978 is a smart switch with no output regulation, but
fault protection and voltage and current monitoring capabilities.
Also it supports upto 4 indication leds.
config MFD_CS47L15
bool "Cirrus Logic CS47L15"
select PINCTRL_CS47L15
......@@ -353,9 +363,6 @@ config MFD_DA9055
Additional drivers must be enabled in order to use the functionality
of the device.
This driver can be built as a module. If built as a module it will be
called "da9055"
config MFD_DA9062
tristate "Dialog Semiconductor DA9062/61 PMIC Support"
select MFD_CORE
......@@ -1308,6 +1315,16 @@ config MFD_SC27XX_PMIC
This driver provides common support for accessing the SC27xx PMICs,
and it also adds the irq_chip parts for handling the PMIC chip events.
config RZ_MTU3
bool "Renesas RZ/G2L MTU3a core driver"
depends on (ARCH_RZG2L && OF) || COMPILE_TEST
help
Select this option to enable Renesas RZ/G2L MTU3a core driver for
the Multi-Function Timer Pulse Unit 3 (MTU3a) hardware available
on SoCs from Renesas. The core driver shares the clk and channel
register access for the other child devices like Counter, PWM,
Clock Source, and Clock event.
config ABX500_CORE
bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions"
depends on ARCH_U8500 || COMPILE_TEST
......
......@@ -174,6 +174,7 @@ pcf50633-objs := pcf50633-core.o pcf50633-irq.o
obj-$(CONFIG_MFD_PCF50633) += pcf50633.o
obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o
obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o
obj-$(CONFIG_RZ_MTU3) += rz-mtu3.o
obj-$(CONFIG_ABX500_CORE) += abx500-core.o
obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o
# ab8500-core need to come after db8500-prcmu (which provides the channel)
......
......@@ -112,6 +112,7 @@ static const struct of_device_id arizona_i2c_of_match[] = {
{ .compatible = "wlf,wm1814", .data = (void *)WM1814 },
{},
};
MODULE_DEVICE_TABLE(of, arizona_i2c_of_match);
#endif
static struct i2c_driver arizona_i2c_driver = {
......
......@@ -277,6 +277,7 @@ static const struct of_device_id arizona_spi_of_match[] = {
{ .compatible = "cirrus,cs47l24", .data = (void *)CS47L24 },
{},
};
MODULE_DEVICE_TABLE(of, arizona_spi_of_match);
#endif
static struct spi_driver arizona_spi_driver = {
......
......@@ -51,7 +51,7 @@ MODULE_DEVICE_TABLE(of, atc260x_i2c_of_match);
static struct i2c_driver atc260x_i2c_driver = {
.driver = {
.name = "atc260x",
.of_match_table = of_match_ptr(atc260x_i2c_of_match),
.of_match_table = atc260x_i2c_of_match,
},
.probe_new = atc260x_i2c_probe,
};
......
......@@ -37,7 +37,6 @@ struct atmel_flexcom {
static int atmel_flexcom_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct resource *res;
struct atmel_flexcom *ddata;
int err;
......@@ -55,8 +54,7 @@ static int atmel_flexcom_probe(struct platform_device *pdev)
ddata->opmode > ATMEL_FLEXCOM_MODE_TWI)
return -EINVAL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ddata->base = devm_ioremap_resource(&pdev->dev, res);
ddata->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(ddata->base))
return PTR_ERR(ddata->base);
......
......@@ -323,7 +323,7 @@ static const struct atmel_hsmc_reg_layout sama5d2_reg_layout = {
.timing_regs_offset = 0x700,
};
static const struct of_device_id atmel_smc_ids[] = {
static const struct of_device_id atmel_smc_ids[] __maybe_unused = {
{ .compatible = "atmel,at91sam9260-smc", .data = NULL },
{ .compatible = "atmel,sama5d3-smc", .data = &sama5d3_reg_layout },
{ .compatible = "atmel,sama5d2-smc", .data = &sama5d2_reg_layout },
......
......@@ -65,6 +65,7 @@ static const struct of_device_id axp20x_i2c_of_match[] = {
{ .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
{ .compatible = "x-powers,axp803", .data = (void *)AXP803_ID },
{ .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
{ .compatible = "x-powers,axp15060", .data = (void *)AXP15060_ID },
{ },
};
MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match);
......@@ -78,6 +79,7 @@ static const struct i2c_device_id axp20x_i2c_id[] = {
{ "axp223", 0 },
{ "axp803", 0 },
{ "axp806", 0 },
{ "axp15060", 0 },
{ },
};
MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
......
......@@ -43,6 +43,7 @@ static const char * const axp20x_model_names[] = {
"AXP806",
"AXP809",
"AXP813",
"AXP15060",
};
static const struct regmap_range axp152_writeable_ranges[] = {
......@@ -119,6 +120,7 @@ static const struct regmap_access_table axp22x_volatile_table = {
/* AXP288 ranges are shared with the AXP803, as they cover the same range */
static const struct regmap_range axp288_writeable_ranges[] = {
regmap_reg_range(AXP288_POWER_REASON, AXP288_POWER_REASON),
regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE),
regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5),
};
......@@ -168,6 +170,31 @@ static const struct regmap_access_table axp806_volatile_table = {
.n_yes_ranges = ARRAY_SIZE(axp806_volatile_ranges),
};
static const struct regmap_range axp15060_writeable_ranges[] = {
regmap_reg_range(AXP15060_PWR_OUT_CTRL1, AXP15060_DCDC_MODE_CTRL2),
regmap_reg_range(AXP15060_OUTPUT_MONITOR_DISCHARGE, AXP15060_CPUSLDO_V_CTRL),
regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ),
regmap_reg_range(AXP15060_PEK_KEY, AXP15060_PEK_KEY),
regmap_reg_range(AXP15060_IRQ1_EN, AXP15060_IRQ2_EN),
regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE),
};
static const struct regmap_range axp15060_volatile_ranges[] = {
regmap_reg_range(AXP15060_STARTUP_SRC, AXP15060_STARTUP_SRC),
regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ),
regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE),
};
static const struct regmap_access_table axp15060_writeable_table = {
.yes_ranges = axp15060_writeable_ranges,
.n_yes_ranges = ARRAY_SIZE(axp15060_writeable_ranges),
};
static const struct regmap_access_table axp15060_volatile_table = {
.yes_ranges = axp15060_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(axp15060_volatile_ranges),
};
static const struct resource axp152_pek_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
......@@ -236,6 +263,11 @@ static const struct resource axp809_pek_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
};
static const struct resource axp15060_pek_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
};
static const struct regmap_config axp152_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
......@@ -281,6 +313,15 @@ static const struct regmap_config axp806_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
static const struct regmap_config axp15060_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.wr_table = &axp15060_writeable_table,
.volatile_table = &axp15060_volatile_table,
.max_register = AXP15060_IRQ2_STATE,
.cache_type = REGCACHE_RBTREE,
};
#define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask) \
[_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
......@@ -502,6 +543,23 @@ static const struct regmap_irq axp809_regmap_irqs[] = {
INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT, 4, 0),
};
static const struct regmap_irq axp15060_regmap_irqs[] = {
INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV1, 0, 0),
INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV2, 0, 1),
INIT_REGMAP_IRQ(AXP15060, DCDC1_V_LOW, 0, 2),
INIT_REGMAP_IRQ(AXP15060, DCDC2_V_LOW, 0, 3),
INIT_REGMAP_IRQ(AXP15060, DCDC3_V_LOW, 0, 4),
INIT_REGMAP_IRQ(AXP15060, DCDC4_V_LOW, 0, 5),
INIT_REGMAP_IRQ(AXP15060, DCDC5_V_LOW, 0, 6),
INIT_REGMAP_IRQ(AXP15060, DCDC6_V_LOW, 0, 7),
INIT_REGMAP_IRQ(AXP15060, PEK_LONG, 1, 0),
INIT_REGMAP_IRQ(AXP15060, PEK_SHORT, 1, 1),
INIT_REGMAP_IRQ(AXP15060, GPIO1_INPUT, 1, 2),
INIT_REGMAP_IRQ(AXP15060, PEK_FAL_EDGE, 1, 3),
INIT_REGMAP_IRQ(AXP15060, PEK_RIS_EDGE, 1, 4),
INIT_REGMAP_IRQ(AXP15060, GPIO2_INPUT, 1, 5),
};
static const struct regmap_irq_chip axp152_regmap_irq_chip = {
.name = "axp152_irq_chip",
.status_base = AXP152_IRQ1_STATE,
......@@ -581,6 +639,17 @@ static const struct regmap_irq_chip axp809_regmap_irq_chip = {
.num_regs = 5,
};
static const struct regmap_irq_chip axp15060_regmap_irq_chip = {
.name = "axp15060",
.status_base = AXP15060_IRQ1_STATE,
.ack_base = AXP15060_IRQ1_STATE,
.unmask_base = AXP15060_IRQ1_EN,
.init_ack_masked = true,
.irqs = axp15060_regmap_irqs,
.num_irqs = ARRAY_SIZE(axp15060_regmap_irqs),
.num_regs = 2,
};
static const struct mfd_cell axp20x_cells[] = {
{
.name = "axp20x-gpio",
......@@ -825,6 +894,23 @@ static const struct mfd_cell axp813_cells[] = {
},
};
static const struct mfd_cell axp15060_cells[] = {
{
.name = "axp221-pek",
.num_resources = ARRAY_SIZE(axp15060_pek_resources),
.resources = axp15060_pek_resources,
}, {
.name = "axp20x-regulator",
},
};
/* For boards that don't have IRQ line connected to SOC. */
static const struct mfd_cell axp_regulator_only_cells[] = {
{
.name = "axp20x-regulator",
},
};
static int axp20x_power_off(struct sys_off_data *data)
{
struct axp20x_dev *axp20x = data->cb_data;
......@@ -934,6 +1020,28 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
*/
axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
break;
case AXP15060_ID:
/*
* Don't register the power key part if there is no interrupt
* line.
*
* Since most use cases of AXP PMICs are Allwinner SOCs, board
* designers follow Allwinner's reference design and connects
* IRQ line to SOC, there's no need for those variants to deal
* with cases that IRQ isn't connected. However, AXP15660 is
* used by some other vendors' SOCs that didn't connect IRQ
* line, we need to deal with this case.
*/
if (axp20x->irq > 0) {
axp20x->nr_cells = ARRAY_SIZE(axp15060_cells);
axp20x->cells = axp15060_cells;
} else {
axp20x->nr_cells = ARRAY_SIZE(axp_regulator_only_cells);
axp20x->cells = axp_regulator_only_cells;
}
axp20x->regmap_cfg = &axp15060_regmap_config;
axp20x->regmap_irq_chip = &axp15060_regmap_irq_chip;
break;
default:
dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);
return -EINVAL;
......
......@@ -28,7 +28,7 @@ static const struct mfd_cell bcm2835_power_devs[] = {
static int bcm2835_pm_get_pdata(struct platform_device *pdev,
struct bcm2835_pm *pm)
{
if (of_find_property(pm->dev->of_node, "reg-names", NULL)) {
if (of_property_present(pm->dev->of_node, "reg-names")) {
struct resource *res;
pm->base = devm_platform_ioremap_resource_byname(pdev, "pm");
......@@ -123,4 +123,3 @@ module_platform_driver(bcm2835_pm_driver);
MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM MFD");
MODULE_LICENSE("GPL");
......@@ -563,4 +563,3 @@ module_exit(da903x_exit);
MODULE_DESCRIPTION("PMIC Driver for Dialog Semiconductor DA9034");
MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
MODULE_LICENSE("GPL v2");
......@@ -653,4 +653,3 @@ void da9052_device_exit(struct da9052 *da9052)
MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
MODULE_DESCRIPTION("DA9052 MFD Core");
MODULE_LICENSE("GPL");
......@@ -209,4 +209,3 @@ module_exit(da9052_i2c_exit);
MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
MODULE_DESCRIPTION("I2C driver for Dialog DA9052 PMIC");
MODULE_LICENSE("GPL");
......@@ -102,4 +102,3 @@ module_exit(da9052_spi_exit);
MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
MODULE_DESCRIPTION("SPI driver for Dialog DA9052 PMIC");
MODULE_LICENSE("GPL");
......@@ -398,5 +398,4 @@ void da9055_device_exit(struct da9055 *da9055)
}
MODULE_DESCRIPTION("Core support for the DA9055 PMIC");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
......@@ -97,4 +97,3 @@ module_exit(da9055_i2c_exit);
MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
MODULE_DESCRIPTION("I2C driver for Dialog DA9055 PMIC");
MODULE_LICENSE("GPL");
......@@ -181,35 +181,25 @@ static const struct resource da9061_onkey_resources[] = {
DEFINE_RES_IRQ_NAMED(DA9061_IRQ_ONKEY, "ONKEY"),
};
static const struct mfd_cell da9061_devs[] = {
{
.name = "da9061-core",
.num_resources = ARRAY_SIZE(da9061_core_resources),
.resources = da9061_core_resources,
},
{
.name = "da9062-regulators",
.num_resources = ARRAY_SIZE(da9061_regulators_resources),
.resources = da9061_regulators_resources,
},
{
.name = "da9061-watchdog",
.num_resources = ARRAY_SIZE(da9061_wdt_resources),
.resources = da9061_wdt_resources,
.of_compatible = "dlg,da9061-watchdog",
},
{
.name = "da9061-thermal",
.num_resources = ARRAY_SIZE(da9061_thermal_resources),
.resources = da9061_thermal_resources,
.of_compatible = "dlg,da9061-thermal",
},
{
.name = "da9061-onkey",
.num_resources = ARRAY_SIZE(da9061_onkey_resources),
.resources = da9061_onkey_resources,
.of_compatible = "dlg,da9061-onkey",
},
static const struct mfd_cell da9061_devs_irq[] = {
MFD_CELL_OF("da9061-core", da9061_core_resources, NULL, 0, 0,
NULL),
MFD_CELL_OF("da9062-regulators", da9061_regulators_resources, NULL, 0, 0,
NULL),
MFD_CELL_OF("da9061-watchdog", da9061_wdt_resources, NULL, 0, 0,
"dlg,da9061-watchdog"),
MFD_CELL_OF("da9061-thermal", da9061_thermal_resources, NULL, 0, 0,
"dlg,da9061-thermal"),
MFD_CELL_OF("da9061-onkey", da9061_onkey_resources, NULL, 0, 0,
"dlg,da9061-onkey"),
};
static const struct mfd_cell da9061_devs_noirq[] = {
MFD_CELL_OF("da9061-core", NULL, NULL, 0, 0, NULL),
MFD_CELL_OF("da9062-regulators", NULL, NULL, 0, 0, NULL),
MFD_CELL_OF("da9061-watchdog", NULL, NULL, 0, 0, "dlg,da9061-watchdog"),
MFD_CELL_OF("da9061-thermal", NULL, NULL, 0, 0, "dlg,da9061-thermal"),
MFD_CELL_OF("da9061-onkey", NULL, NULL, 0, 0, "dlg,da9061-onkey"),
};
static const struct resource da9062_core_resources[] = {
......@@ -245,47 +235,31 @@ static const struct resource da9062_gpio_resources[] = {
DEFINE_RES_NAMED(DA9062_IRQ_GPI4, 1, "GPI4", IORESOURCE_IRQ),
};
static const struct mfd_cell da9062_devs[] = {
{
.name = "da9062-core",
.num_resources = ARRAY_SIZE(da9062_core_resources),
.resources = da9062_core_resources,
},
{
.name = "da9062-regulators",
.num_resources = ARRAY_SIZE(da9062_regulators_resources),
.resources = da9062_regulators_resources,
},
{
.name = "da9062-watchdog",
.num_resources = ARRAY_SIZE(da9062_wdt_resources),
.resources = da9062_wdt_resources,
.of_compatible = "dlg,da9062-watchdog",
},
{
.name = "da9062-thermal",
.num_resources = ARRAY_SIZE(da9062_thermal_resources),
.resources = da9062_thermal_resources,
.of_compatible = "dlg,da9062-thermal",
},
{
.name = "da9062-rtc",
.num_resources = ARRAY_SIZE(da9062_rtc_resources),
.resources = da9062_rtc_resources,
.of_compatible = "dlg,da9062-rtc",
},
{
.name = "da9062-onkey",
.num_resources = ARRAY_SIZE(da9062_onkey_resources),
.resources = da9062_onkey_resources,
.of_compatible = "dlg,da9062-onkey",
},
{
.name = "da9062-gpio",
.num_resources = ARRAY_SIZE(da9062_gpio_resources),
.resources = da9062_gpio_resources,
.of_compatible = "dlg,da9062-gpio",
},
static const struct mfd_cell da9062_devs_irq[] = {
MFD_CELL_OF("da9062-core", da9062_core_resources, NULL, 0, 0,
NULL),
MFD_CELL_OF("da9062-regulators", da9062_regulators_resources, NULL, 0, 0,
NULL),
MFD_CELL_OF("da9062-watchdog", da9062_wdt_resources, NULL, 0, 0,
"dlg,da9062-watchdog"),
MFD_CELL_OF("da9062-thermal", da9062_thermal_resources, NULL, 0, 0,
"dlg,da9062-thermal"),
MFD_CELL_OF("da9062-rtc", da9062_rtc_resources, NULL, 0, 0,
"dlg,da9062-rtc"),
MFD_CELL_OF("da9062-onkey", da9062_onkey_resources, NULL, 0, 0,
"dlg,da9062-onkey"),
MFD_CELL_OF("da9062-gpio", da9062_gpio_resources, NULL, 0, 0,
"dlg,da9062-gpio"),
};
static const struct mfd_cell da9062_devs_noirq[] = {
MFD_CELL_OF("da9062-core", NULL, NULL, 0, 0, NULL),
MFD_CELL_OF("da9062-regulators", NULL, NULL, 0, 0, NULL),
MFD_CELL_OF("da9062-watchdog", NULL, NULL, 0, 0, "dlg,da9062-watchdog"),
MFD_CELL_OF("da9062-thermal", NULL, NULL, 0, 0, "dlg,da9062-thermal"),
MFD_CELL_OF("da9062-rtc", NULL, NULL, 0, 0, "dlg,da9062-rtc"),
MFD_CELL_OF("da9062-onkey", NULL, NULL, 0, 0, "dlg,da9062-onkey"),
MFD_CELL_OF("da9062-gpio", NULL, NULL, 0, 0, "dlg,da9062-gpio"),
};
static int da9062_clear_fault_log(struct da9062 *chip)
......@@ -625,7 +599,7 @@ static int da9062_i2c_probe(struct i2c_client *i2c)
{
const struct i2c_device_id *id = i2c_client_get_device_id(i2c);
struct da9062 *chip;
unsigned int irq_base;
unsigned int irq_base = 0;
const struct mfd_cell *cell;
const struct regmap_irq_chip *irq_chip;
const struct regmap_config *config;
......@@ -645,22 +619,16 @@ static int da9062_i2c_probe(struct i2c_client *i2c)
i2c_set_clientdata(i2c, chip);
chip->dev = &i2c->dev;
if (!i2c->irq) {
dev_err(chip->dev, "No IRQ configured\n");
return -EINVAL;
}
/* Start with a base configuration without IRQ */
switch (chip->chip_type) {
case COMPAT_TYPE_DA9061:
cell = da9061_devs;
cell_num = ARRAY_SIZE(da9061_devs);
irq_chip = &da9061_irq_chip;
cell = da9061_devs_noirq;
cell_num = ARRAY_SIZE(da9061_devs_noirq);
config = &da9061_regmap_config;
break;
case COMPAT_TYPE_DA9062:
cell = da9062_devs;
cell_num = ARRAY_SIZE(da9062_devs);
irq_chip = &da9062_irq_chip;
cell = da9062_devs_noirq;
cell_num = ARRAY_SIZE(da9062_devs_noirq);
config = &da9062_regmap_config;
break;
default:
......@@ -695,29 +663,43 @@ static int da9062_i2c_probe(struct i2c_client *i2c)
if (ret)
return ret;
ret = da9062_configure_irq_type(chip, i2c->irq, &trigger_type);
if (ret < 0) {
dev_err(chip->dev, "Failed to configure IRQ type\n");
return ret;
}
/* If IRQ is available, reconfigure it accordingly */
if (i2c->irq) {
if (chip->chip_type == COMPAT_TYPE_DA9061) {
cell = da9061_devs_irq;
cell_num = ARRAY_SIZE(da9061_devs_irq);
irq_chip = &da9061_irq_chip;
} else {
cell = da9062_devs_irq;
cell_num = ARRAY_SIZE(da9062_devs_irq);
irq_chip = &da9062_irq_chip;
}
ret = regmap_add_irq_chip(chip->regmap, i2c->irq,
trigger_type | IRQF_SHARED | IRQF_ONESHOT,
-1, irq_chip, &chip->regmap_irq);
if (ret) {
dev_err(chip->dev, "Failed to request IRQ %d: %d\n",
i2c->irq, ret);
return ret;
}
ret = da9062_configure_irq_type(chip, i2c->irq, &trigger_type);
if (ret < 0) {
dev_err(chip->dev, "Failed to configure IRQ type\n");
return ret;
}
irq_base = regmap_irq_chip_get_base(chip->regmap_irq);
ret = regmap_add_irq_chip(chip->regmap, i2c->irq,
trigger_type | IRQF_SHARED | IRQF_ONESHOT,
-1, irq_chip, &chip->regmap_irq);
if (ret) {
dev_err(chip->dev, "Failed to request IRQ %d: %d\n",
i2c->irq, ret);
return ret;
}
irq_base = regmap_irq_chip_get_base(chip->regmap_irq);
}
ret = mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE, cell,
cell_num, NULL, irq_base,
NULL);
if (ret) {
dev_err(chip->dev, "Cannot register child devices\n");
regmap_del_irq_chip(i2c->irq, chip->regmap_irq);
if (i2c->irq)
regmap_del_irq_chip(i2c->irq, chip->regmap_irq);
return ret;
}
......
......@@ -827,6 +827,7 @@ static int dln2_probe(struct usb_interface *interface,
dln2_stop_rx_urbs(dln2);
out_free:
usb_put_dev(dln2->usb_dev);
dln2_free(dln2);
return ret;
......
......@@ -528,7 +528,6 @@ static void __exit ezx_pcap_exit(void)
subsys_initcall(ezx_pcap_init);
module_exit(ezx_pcap_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Daniel Ribeiro / Harald Welte");
MODULE_DESCRIPTION("Motorola PCAP2 ASIC Driver");
MODULE_ALIAS("spi:ezx-pcap");
......@@ -50,7 +50,6 @@ MODULE_DEVICE_TABLE(of, of_hi6421_pmic_match);
static int hi6421_pmic_probe(struct platform_device *pdev)
{
struct hi6421_pmic *pmic;
struct resource *res;
const struct of_device_id *id;
const struct mfd_cell *subdevs;
enum hi6421_type type;
......@@ -66,8 +65,7 @@ static int hi6421_pmic_probe(struct platform_device *pdev)
if (!pmic)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(base))
return PTR_ERR(base);
......
......@@ -447,6 +447,21 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x7e79), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7e7a), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7e7b), (kernel_ulong_t)&bxt_i2c_info },
/* MTP-S */
{ PCI_VDEVICE(INTEL, 0x7f28), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x7f29), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x7f2a), (kernel_ulong_t)&tgl_info },
{ PCI_VDEVICE(INTEL, 0x7f2b), (kernel_ulong_t)&tgl_info },
{ PCI_VDEVICE(INTEL, 0x7f4c), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7f4d), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7f4e), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7f4f), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7f5c), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x7f5d), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x7f5e), (kernel_ulong_t)&tgl_info },
{ PCI_VDEVICE(INTEL, 0x7f5f), (kernel_ulong_t)&tgl_info },
{ PCI_VDEVICE(INTEL, 0x7f7a), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7f7b), (kernel_ulong_t)&bxt_i2c_info },
/* LKF */
{ PCI_VDEVICE(INTEL, 0x98a8), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x98a9), (kernel_ulong_t)&bxt_uart_info },
......
......@@ -159,11 +159,19 @@ static const struct dmi_system_id cht_wc_model_dmi_ids[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"),
},
}, {
/* Lenovo Yoga Book X90F / X91F / X91L */
/* Lenovo Yoga Book X90F / X90L */
.driver_data = (void *)(long)INTEL_CHT_WC_LENOVO_YOGABOOK1,
.matches = {
/* Non exact match to match all versions */
DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9"),
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
},
}, {
/* Lenovo Yoga Book X91F / X91L */
.driver_data = (void *)(long)INTEL_CHT_WC_LENOVO_YOGABOOK1,
.matches = {
/* Non exact match to match F + L versions */
DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X91"),
},
}, {
/* Lenovo Yoga Tab 3 Pro YT3-X90F */
......
......@@ -271,6 +271,5 @@ static struct i2c_driver crystal_cove_i2c_driver = {
module_i2c_driver(crystal_cove_i2c_driver);
MODULE_DESCRIPTION("I2C driver for Intel SoC PMIC");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Yang, Bin <bin.yang@intel.com>");
MODULE_AUTHOR("Zhu, Lejun <lejun.zhu@linux.intel.com>");
......@@ -381,7 +381,6 @@ static int __maybe_unused micro_resume(struct device *dev)
static int __init micro_probe(struct platform_device *pdev)
{
struct ipaq_micro *micro;
struct resource *res;
int ret;
int irq;
......@@ -391,8 +390,7 @@ static int __init micro_probe(struct platform_device *pdev)
micro->dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
micro->base = devm_ioremap_resource(&pdev->dev, res);
micro->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(micro->base))
return PTR_ERR(micro->base);
......
......@@ -112,7 +112,7 @@ static int khadas_mcu_probe(struct i2c_client *client)
if (ret)
return ret;
if (of_find_property(dev->of_node, "#cooling-cells", NULL))
if (of_property_present(dev->of_node, "#cooling-cells"))
return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
khadas_mcu_fan_cells,
ARRAY_SIZE(khadas_mcu_fan_cells),
......
......@@ -244,4 +244,3 @@ module_exit(lp8788_exit);
MODULE_DESCRIPTION("TI LP8788 MFD Driver");
MODULE_AUTHOR("Milo Kim");
MODULE_LICENSE("GPL");
......@@ -33,32 +33,6 @@ static struct device_type mfd_dev_type = {
.name = "mfd_device",
};
int mfd_cell_enable(struct platform_device *pdev)
{
const struct mfd_cell *cell = mfd_get_cell(pdev);
if (!cell->enable) {
dev_dbg(&pdev->dev, "No .enable() call-back registered\n");
return 0;
}
return cell->enable(pdev);
}
EXPORT_SYMBOL(mfd_cell_enable);
int mfd_cell_disable(struct platform_device *pdev)
{
const struct mfd_cell *cell = mfd_get_cell(pdev);
if (!cell->disable) {
dev_dbg(&pdev->dev, "No .disable() call-back registered\n");
return 0;
}
return cell->disable(pdev);
}
EXPORT_SYMBOL(mfd_cell_disable);
#if IS_ENABLED(CONFIG_ACPI)
struct match_ids_walk_data {
struct acpi_device_id *ids;
......
......@@ -130,6 +130,7 @@ static const struct regmap_config ocelot_spi_regmap_config = {
.write_flag_mask = 0x80,
.use_single_read = true,
.use_single_write = true,
.can_multi_write = false,
......
......@@ -853,7 +853,6 @@ static struct platform_driver usbhs_omap_driver = {
MODULE_AUTHOR("Keshava Munegowda <keshava_mgowda@ti.com>");
MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>");
MODULE_ALIAS("platform:" USBHS_DRIVER_NAME);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("usb host common core driver for omap EHCI and OHCI");
static int omap_usbhs_drvinit(void)
......
......@@ -125,11 +125,6 @@ static inline void usbtll_writeb(void __iomem *base, u32 reg, u8 val)
writeb_relaxed(val, base + reg);
}
static inline u8 usbtll_readb(void __iomem *base, u32 reg)
{
return readb_relaxed(base + reg);
}
/*-------------------------------------------------------------------------*/
static bool is_ohci_port(enum usbhs_omap_port_mode pmode)
......@@ -450,7 +445,6 @@ EXPORT_SYMBOL_GPL(omap_tll_disable);
MODULE_AUTHOR("Keshava Munegowda <keshava_mgowda@ti.com>");
MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("usb tll driver for TI OMAP EHCI and OHCI controllers");
static int __init omap_usbtll_drvinit(void)
......
......@@ -44,37 +44,16 @@ enum {
#define PM8008_GPIO1_ADDR PM8008_PERIPH_2_BASE
#define PM8008_GPIO2_ADDR PM8008_PERIPH_3_BASE
#define PM8008_STATUS_BASE (PM8008_PERIPH_0_BASE | INT_LATCHED_STS_OFFSET)
#define PM8008_MASK_BASE (PM8008_PERIPH_0_BASE | INT_EN_SET_OFFSET)
#define PM8008_UNMASK_BASE (PM8008_PERIPH_0_BASE | INT_EN_CLR_OFFSET)
#define PM8008_TYPE_BASE (PM8008_PERIPH_0_BASE | INT_SET_TYPE_OFFSET)
#define PM8008_ACK_BASE (PM8008_PERIPH_0_BASE | INT_LATCHED_CLR_OFFSET)
#define PM8008_POLARITY_HI_BASE (PM8008_PERIPH_0_BASE | INT_POL_HIGH_OFFSET)
#define PM8008_POLARITY_LO_BASE (PM8008_PERIPH_0_BASE | INT_POL_LOW_OFFSET)
#define PM8008_PERIPH_OFFSET(paddr) (paddr - PM8008_PERIPH_0_BASE)
static unsigned int p0_offs[] = {PM8008_PERIPH_OFFSET(PM8008_PERIPH_0_BASE)};
static unsigned int p1_offs[] = {PM8008_PERIPH_OFFSET(PM8008_PERIPH_1_BASE)};
static unsigned int p2_offs[] = {PM8008_PERIPH_OFFSET(PM8008_PERIPH_2_BASE)};
static unsigned int p3_offs[] = {PM8008_PERIPH_OFFSET(PM8008_PERIPH_3_BASE)};
static struct regmap_irq_sub_irq_map pm8008_sub_reg_offsets[] = {
REGMAP_IRQ_MAIN_REG_OFFSET(p0_offs),
REGMAP_IRQ_MAIN_REG_OFFSET(p1_offs),
REGMAP_IRQ_MAIN_REG_OFFSET(p2_offs),
REGMAP_IRQ_MAIN_REG_OFFSET(p3_offs),
};
static unsigned int pm8008_virt_regs[] = {
PM8008_POLARITY_HI_BASE,
PM8008_POLARITY_LO_BASE,
};
enum {
SET_TYPE_INDEX,
POLARITY_HI_INDEX,
POLARITY_LO_INDEX,
PM8008_NUM_VIRT_REGS,
};
static unsigned int pm8008_config_regs[] = {
INT_SET_TYPE_OFFSET,
INT_POL_HIGH_OFFSET,
INT_POL_LOW_OFFSET,
};
static struct regmap_irq pm8008_irqs[] = {
......@@ -88,32 +67,54 @@ static struct regmap_irq pm8008_irqs[] = {
REGMAP_IRQ_REG(PM8008_IRQ_GPIO2, PM8008_GPIO2, BIT(0)),
};
static int pm8008_set_type_virt(unsigned int **virt_buf,
unsigned int type, unsigned long hwirq,
int reg)
static const unsigned int pm8008_periph_base[] = {
PM8008_PERIPH_0_BASE,
PM8008_PERIPH_1_BASE,
PM8008_PERIPH_2_BASE,
PM8008_PERIPH_3_BASE,
};
static unsigned int pm8008_get_irq_reg(struct regmap_irq_chip_data *data,
unsigned int base, int index)
{
/* Simple linear addressing for the main status register */
if (base == I2C_INTR_STATUS_BASE)
return base + index;
return pm8008_periph_base[index] + base;
}
static int pm8008_set_type_config(unsigned int **buf, unsigned int type,
const struct regmap_irq *irq_data, int idx,
void *irq_drv_data)
{
switch (type) {
case IRQ_TYPE_EDGE_FALLING:
case IRQ_TYPE_LEVEL_LOW:
virt_buf[POLARITY_HI_INDEX][reg] &= ~pm8008_irqs[hwirq].mask;
virt_buf[POLARITY_LO_INDEX][reg] |= pm8008_irqs[hwirq].mask;
buf[POLARITY_HI_INDEX][idx] &= ~irq_data->mask;
buf[POLARITY_LO_INDEX][idx] |= irq_data->mask;
break;
case IRQ_TYPE_EDGE_RISING:
case IRQ_TYPE_LEVEL_HIGH:
virt_buf[POLARITY_HI_INDEX][reg] |= pm8008_irqs[hwirq].mask;
virt_buf[POLARITY_LO_INDEX][reg] &= ~pm8008_irqs[hwirq].mask;
buf[POLARITY_HI_INDEX][idx] |= irq_data->mask;
buf[POLARITY_LO_INDEX][idx] &= ~irq_data->mask;
break;
case IRQ_TYPE_EDGE_BOTH:
virt_buf[POLARITY_HI_INDEX][reg] |= pm8008_irqs[hwirq].mask;
virt_buf[POLARITY_LO_INDEX][reg] |= pm8008_irqs[hwirq].mask;
buf[POLARITY_HI_INDEX][idx] |= irq_data->mask;
buf[POLARITY_LO_INDEX][idx] |= irq_data->mask;
break;
default:
return -EINVAL;
}
if (type & IRQ_TYPE_EDGE_BOTH)
buf[SET_TYPE_INDEX][idx] |= irq_data->mask;
else
buf[SET_TYPE_INDEX][idx] &= ~irq_data->mask;
return 0;
}
......@@ -121,20 +122,19 @@ static struct regmap_irq_chip pm8008_irq_chip = {
.name = "pm8008_irq",
.main_status = I2C_INTR_STATUS_BASE,
.num_main_regs = 1,
.num_virt_regs = PM8008_NUM_VIRT_REGS,
.irqs = pm8008_irqs,
.num_irqs = ARRAY_SIZE(pm8008_irqs),
.num_regs = PM8008_NUM_PERIPHS,
.not_fixed_stride = true,
.sub_reg_offsets = pm8008_sub_reg_offsets,
.set_type_virt = pm8008_set_type_virt,
.status_base = PM8008_STATUS_BASE,
.mask_base = PM8008_MASK_BASE,
.unmask_base = PM8008_UNMASK_BASE,
.type_base = PM8008_TYPE_BASE,
.ack_base = PM8008_ACK_BASE,
.virt_reg_base = pm8008_virt_regs,
.num_type_reg = PM8008_NUM_PERIPHS,
.status_base = INT_LATCHED_STS_OFFSET,
.mask_base = INT_EN_CLR_OFFSET,
.unmask_base = INT_EN_SET_OFFSET,
.mask_unmask_non_inverted = true,
.ack_base = INT_LATCHED_CLR_OFFSET,
.config_base = pm8008_config_regs,
.num_config_bases = ARRAY_SIZE(pm8008_config_regs),
.num_config_regs = PM8008_NUM_PERIPHS,
.set_type_config = pm8008_set_type_config,
.get_irq_reg = pm8008_get_irq_reg,
};
static struct regmap_config qcom_mfd_regmap_cfg = {
......@@ -143,30 +143,6 @@ static struct regmap_config qcom_mfd_regmap_cfg = {
.max_register = 0xFFFF,
};
static int pm8008_init(struct regmap *regmap)
{
int rc;
/*
* Set TEMP_ALARM peripheral's TYPE so that the regmap-irq framework
* reads this as the default value instead of zero, the HW default.
* This is required to enable the writing of TYPE registers in
* regmap_irq_sync_unlock().
*/
rc = regmap_write(regmap, (PM8008_TEMP_ALARM_ADDR | INT_SET_TYPE_OFFSET), BIT(0));
if (rc)
return rc;
/* Do the same for GPIO1 and GPIO2 peripherals */
rc = regmap_write(regmap, (PM8008_GPIO1_ADDR | INT_SET_TYPE_OFFSET), BIT(0));
if (rc)
return rc;
rc = regmap_write(regmap, (PM8008_GPIO2_ADDR | INT_SET_TYPE_OFFSET), BIT(0));
return rc;
}
static int pm8008_probe_irq_peripherals(struct device *dev,
struct regmap *regmap,
int client_irq)
......@@ -175,20 +151,10 @@ static int pm8008_probe_irq_peripherals(struct device *dev,
struct regmap_irq_type *type;
struct regmap_irq_chip_data *irq_data;
rc = pm8008_init(regmap);
if (rc) {
dev_err(dev, "Init failed: %d\n", rc);
return rc;
}
for (i = 0; i < ARRAY_SIZE(pm8008_irqs); i++) {
type = &pm8008_irqs[i].type;
type->type_reg_offset = pm8008_irqs[i].reg_offset;
type->type_rising_val = pm8008_irqs[i].mask;
type->type_falling_val = pm8008_irqs[i].mask;
type->type_level_high_val = 0;
type->type_level_low_val = 0;
type->type_reg_offset = pm8008_irqs[i].reg_offset;
if (type->type_reg_offset == PM8008_MISC)
type->types_supported = IRQ_TYPE_EDGE_RISING;
......
......@@ -530,7 +530,6 @@ static int qcom_rpm_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
struct device_node *syscon_np;
struct resource *res;
struct qcom_rpm *rpm;
u32 fw_version[3];
int irq_wakeup;
......@@ -576,8 +575,7 @@ static int qcom_rpm_probe(struct platform_device *pdev)
return -ENODEV;
rpm->data = match->data;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rpm->status_regs = devm_ioremap_resource(&pdev->dev, res);
rpm->status_regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(rpm->status_regs))
return PTR_ERR(rpm->status_regs);
rpm->ctrl_regs = rpm->status_regs + 0x400;
......
......@@ -10,6 +10,8 @@
#include <linux/mfd/rsmu.h>
#define RSMU_CM_SCSR_BASE 0x20100000
int rsmu_core_init(struct rsmu_ddata *rsmu);
void rsmu_core_exit(struct rsmu_ddata *rsmu);
......
......@@ -18,11 +18,12 @@
#include "rsmu.h"
/*
* 16-bit register address: the lower 8 bits of the register address come
* from the offset addr byte and the upper 8 bits come from the page register.
* 32-bit register address: the lower 8 bits of the register address come
* from the offset addr byte and the upper 24 bits come from the page register.
*/
#define RSMU_CM_PAGE_ADDR 0xFD
#define RSMU_CM_PAGE_WINDOW 256
#define RSMU_CM_PAGE_ADDR 0xFC
#define RSMU_CM_PAGE_MASK 0xFFFFFF00
#define RSMU_CM_ADDRESS_MASK 0x000000FF
/*
* 15-bit register address: the lower 7 bits of the register address come
......@@ -31,18 +32,6 @@
#define RSMU_SABRE_PAGE_ADDR 0x7F
#define RSMU_SABRE_PAGE_WINDOW 128
static const struct regmap_range_cfg rsmu_cm_range_cfg[] = {
{
.range_min = 0,
.range_max = 0xD000,
.selector_reg = RSMU_CM_PAGE_ADDR,
.selector_mask = 0xFF,
.selector_shift = 0,
.window_start = 0,
.window_len = RSMU_CM_PAGE_WINDOW,
}
};
static const struct regmap_range_cfg rsmu_sabre_range_cfg[] = {
{
.range_min = 0,
......@@ -55,35 +44,141 @@ static const struct regmap_range_cfg rsmu_sabre_range_cfg[] = {
}
};
static bool rsmu_cm_volatile_reg(struct device *dev, unsigned int reg)
static bool rsmu_sabre_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case RSMU_CM_PAGE_ADDR:
case RSMU_SABRE_PAGE_ADDR:
return false;
default:
return true;
}
}
static bool rsmu_sabre_volatile_reg(struct device *dev, unsigned int reg)
static int rsmu_read_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes)
{
switch (reg) {
case RSMU_SABRE_PAGE_ADDR:
return false;
default:
return true;
struct i2c_client *client = to_i2c_client(rsmu->dev);
struct i2c_msg msg[2];
int cnt;
msg[0].addr = client->addr;
msg[0].flags = 0;
msg[0].len = 1;
msg[0].buf = &reg;
msg[1].addr = client->addr;
msg[1].flags = I2C_M_RD;
msg[1].len = bytes;
msg[1].buf = buf;
cnt = i2c_transfer(client->adapter, msg, 2);
if (cnt < 0) {
dev_err(rsmu->dev, "i2c_transfer failed at addr: %04x!", reg);
return cnt;
} else if (cnt != 2) {
dev_err(rsmu->dev,
"i2c_transfer sent only %d of 2 messages", cnt);
return -EIO;
}
return 0;
}
static int rsmu_write_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes)
{
struct i2c_client *client = to_i2c_client(rsmu->dev);
u8 msg[RSMU_MAX_WRITE_COUNT + 1]; /* 1 Byte added for the device register */
int cnt;
if (bytes > RSMU_MAX_WRITE_COUNT)
return -EINVAL;
msg[0] = reg;
memcpy(&msg[1], buf, bytes);
cnt = i2c_master_send(client, msg, bytes + 1);
if (cnt < 0) {
dev_err(&client->dev,
"i2c_master_send failed at addr: %04x!", reg);
return cnt;
}
return 0;
}
static int rsmu_write_page_register(struct rsmu_ddata *rsmu, u32 reg)
{
u32 page = reg & RSMU_CM_PAGE_MASK;
u8 buf[4];
int err;
/* Do not modify offset register for none-scsr registers */
if (reg < RSMU_CM_SCSR_BASE)
return 0;
/* Simply return if we are on the same page */
if (rsmu->page == page)
return 0;
buf[0] = 0x0;
buf[1] = (u8)((page >> 8) & 0xFF);
buf[2] = (u8)((page >> 16) & 0xFF);
buf[3] = (u8)((page >> 24) & 0xFF);
err = rsmu_write_device(rsmu, RSMU_CM_PAGE_ADDR, buf, sizeof(buf));
if (err)
dev_err(rsmu->dev, "Failed to set page offset 0x%x\n", page);
else
/* Remember the last page */
rsmu->page = page;
return err;
}
static int rsmu_reg_read(void *context, unsigned int reg, unsigned int *val)
{
struct rsmu_ddata *rsmu = i2c_get_clientdata((struct i2c_client *)context);
u8 addr = (u8)(reg & RSMU_CM_ADDRESS_MASK);
int err;
err = rsmu_write_page_register(rsmu, reg);
if (err)
return err;
err = rsmu_read_device(rsmu, addr, (u8 *)val, 1);
if (err)
dev_err(rsmu->dev, "Failed to read offset address 0x%x\n", addr);
return err;
}
static int rsmu_reg_write(void *context, unsigned int reg, unsigned int val)
{
struct rsmu_ddata *rsmu = i2c_get_clientdata((struct i2c_client *)context);
u8 addr = (u8)(reg & RSMU_CM_ADDRESS_MASK);
u8 data = (u8)val;
int err;
err = rsmu_write_page_register(rsmu, reg);
if (err)
return err;
err = rsmu_write_device(rsmu, addr, &data, 1);
if (err)
dev_err(rsmu->dev,
"Failed to write offset address 0x%x\n", addr);
return err;
}
static const struct regmap_config rsmu_cm_regmap_config = {
.reg_bits = 8,
.reg_bits = 32,
.val_bits = 8,
.max_register = 0xD000,
.ranges = rsmu_cm_range_cfg,
.num_ranges = ARRAY_SIZE(rsmu_cm_range_cfg),
.volatile_reg = rsmu_cm_volatile_reg,
.cache_type = REGCACHE_RBTREE,
.can_multi_write = true,
.max_register = 0x20120000,
.reg_read = rsmu_reg_read,
.reg_write = rsmu_reg_write,
.cache_type = REGCACHE_NONE,
};
static const struct regmap_config rsmu_sabre_regmap_config = {
......@@ -101,7 +196,7 @@ static const struct regmap_config rsmu_sl_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
.reg_format_endian = REGMAP_ENDIAN_BIG,
.max_register = 0x339,
.max_register = 0x340,
.cache_type = REGCACHE_NONE,
.can_multi_write = true,
};
......@@ -136,7 +231,11 @@ static int rsmu_i2c_probe(struct i2c_client *client)
dev_err(rsmu->dev, "Unsupported RSMU device type: %d\n", rsmu->type);
return -ENODEV;
}
rsmu->regmap = devm_regmap_init_i2c(client, cfg);
if (rsmu->type == RSMU_CM)
rsmu->regmap = devm_regmap_init(&client->dev, NULL, client, cfg);
else
rsmu->regmap = devm_regmap_init_i2c(client, cfg);
if (IS_ERR(rsmu->regmap)) {
ret = PTR_ERR(rsmu->regmap);
dev_err(rsmu->dev, "Failed to allocate register map: %d\n", ret);
......
......@@ -19,19 +19,21 @@
#define RSMU_CM_PAGE_ADDR 0x7C
#define RSMU_SABRE_PAGE_ADDR 0x7F
#define RSMU_HIGHER_ADDR_MASK 0xFF80
#define RSMU_HIGHER_ADDR_SHIFT 7
#define RSMU_LOWER_ADDR_MASK 0x7F
#define RSMU_PAGE_MASK 0xFFFFFF80
#define RSMU_ADDR_MASK 0x7F
static int rsmu_read_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes)
{
struct spi_device *client = to_spi_device(rsmu->dev);
struct spi_transfer xfer = {0};
struct spi_message msg;
u8 cmd[256] = {0};
u8 rsp[256] = {0};
u8 cmd[RSMU_MAX_READ_COUNT + 1] = {0};
u8 rsp[RSMU_MAX_READ_COUNT + 1] = {0};
int ret;
if (bytes > RSMU_MAX_READ_COUNT)
return -EINVAL;
cmd[0] = reg | 0x80;
xfer.rx_buf = rsp;
xfer.len = bytes + 1;
......@@ -66,7 +68,10 @@ static int rsmu_write_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes
struct spi_device *client = to_spi_device(rsmu->dev);
struct spi_transfer xfer = {0};
struct spi_message msg;
u8 cmd[256] = {0};
u8 cmd[RSMU_MAX_WRITE_COUNT + 1] = {0};
if (bytes > RSMU_MAX_WRITE_COUNT)
return -EINVAL;
cmd[0] = reg;
memcpy(&cmd[1], buf, bytes);
......@@ -86,26 +91,35 @@ static int rsmu_write_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes
* 16-bit register address: the lower 7 bits of the register address come
* from the offset addr byte and the upper 9 bits come from the page register.
*/
static int rsmu_write_page_register(struct rsmu_ddata *rsmu, u16 reg)
static int rsmu_write_page_register(struct rsmu_ddata *rsmu, u32 reg)
{
u8 page_reg;
u8 buf[2];
u8 buf[4];
u16 bytes;
u16 page;
u32 page;
int err;
switch (rsmu->type) {
case RSMU_CM:
/* Do not modify page register for none-scsr registers */
if (reg < RSMU_CM_SCSR_BASE)
return 0;
page_reg = RSMU_CM_PAGE_ADDR;
page = reg & RSMU_HIGHER_ADDR_MASK;
page = reg & RSMU_PAGE_MASK;
buf[0] = (u8)(page & 0xff);
buf[1] = (u8)((page >> 8) & 0xff);
bytes = 2;
buf[2] = (u8)((page >> 16) & 0xff);
buf[3] = (u8)((page >> 24) & 0xff);
bytes = 4;
break;
case RSMU_SABRE:
/* Do not modify page register if reg is page register itself */
if ((reg & RSMU_ADDR_MASK) == RSMU_ADDR_MASK)
return 0;
page_reg = RSMU_SABRE_PAGE_ADDR;
page = reg >> RSMU_HIGHER_ADDR_SHIFT;
buf[0] = (u8)(page & 0xff);
page = reg & RSMU_PAGE_MASK;
/* The three page bits are located in the single Page Register */
buf[0] = (u8)((page >> 7) & 0x7);
bytes = 1;
break;
default:
......@@ -130,7 +144,7 @@ static int rsmu_write_page_register(struct rsmu_ddata *rsmu, u16 reg)
static int rsmu_reg_read(void *context, unsigned int reg, unsigned int *val)
{
struct rsmu_ddata *rsmu = spi_get_drvdata((struct spi_device *)context);
u8 addr = (u8)(reg & RSMU_LOWER_ADDR_MASK);
u8 addr = (u8)(reg & RSMU_ADDR_MASK);
int err;
err = rsmu_write_page_register(rsmu, reg);
......@@ -147,7 +161,7 @@ static int rsmu_reg_read(void *context, unsigned int reg, unsigned int *val)
static int rsmu_reg_write(void *context, unsigned int reg, unsigned int val)
{
struct rsmu_ddata *rsmu = spi_get_drvdata((struct spi_device *)context);
u8 addr = (u8)(reg & RSMU_LOWER_ADDR_MASK);
u8 addr = (u8)(reg & RSMU_ADDR_MASK);
u8 data = (u8)val;
int err;
......@@ -164,9 +178,9 @@ static int rsmu_reg_write(void *context, unsigned int reg, unsigned int val)
}
static const struct regmap_config rsmu_cm_regmap_config = {
.reg_bits = 16,
.reg_bits = 32,
.val_bits = 8,
.max_register = 0xD000,
.max_register = 0x20120000,
.reg_read = rsmu_reg_read,
.reg_write = rsmu_reg_write,
.cache_type = REGCACHE_NONE,
......
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas RZ/G2L Multi-Function Timer Pulse Unit 3(MTU3a) Core driver
*
* Copyright (C) 2023 Renesas Electronics Corporation
*/
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/mfd/core.h>
#include <linux/mfd/rz-mtu3.h>
#include <linux/of_platform.h>
#include <linux/reset.h>
#include <linux/spinlock.h>
#include "rz-mtu3.h"
struct rz_mtu3_priv {
void __iomem *mmio;
struct reset_control *rstc;
raw_spinlock_t lock;
};
/******* MTU3 registers (original offset is +0x1200) *******/
static const unsigned long rz_mtu3_8bit_ch_reg_offs[][13] = {
[RZ_MTU3_CHAN_0] = MTU_8BIT_CH_0(0x104, 0x090, 0x100, 0x128, 0x101, 0x102, 0x103, 0x126),
[RZ_MTU3_CHAN_1] = MTU_8BIT_CH_1_2(0x184, 0x091, 0x185, 0x180, 0x194, 0x181, 0x182),
[RZ_MTU3_CHAN_2] = MTU_8BIT_CH_1_2(0x204, 0x092, 0x205, 0x200, 0x20c, 0x201, 0x202),
[RZ_MTU3_CHAN_3] = MTU_8BIT_CH_3_4_6_7(0x008, 0x093, 0x02c, 0x000, 0x04c, 0x002, 0x004, 0x005, 0x038),
[RZ_MTU3_CHAN_4] = MTU_8BIT_CH_3_4_6_7(0x009, 0x094, 0x02d, 0x001, 0x04d, 0x003, 0x006, 0x007, 0x039),
[RZ_MTU3_CHAN_5] = MTU_8BIT_CH_5(0xab2, 0x1eb, 0xab4, 0xab6, 0xa84, 0xa85, 0xa86, 0xa94, 0xa95, 0xa96, 0xaa4, 0xaa5, 0xaa6),
[RZ_MTU3_CHAN_6] = MTU_8BIT_CH_3_4_6_7(0x808, 0x893, 0x82c, 0x800, 0x84c, 0x802, 0x804, 0x805, 0x838),
[RZ_MTU3_CHAN_7] = MTU_8BIT_CH_3_4_6_7(0x809, 0x894, 0x82d, 0x801, 0x84d, 0x803, 0x806, 0x807, 0x839),
[RZ_MTU3_CHAN_8] = MTU_8BIT_CH_8(0x404, 0x098, 0x400, 0x406, 0x401, 0x402, 0x403)
};
static const unsigned long rz_mtu3_16bit_ch_reg_offs[][12] = {
[RZ_MTU3_CHAN_0] = MTU_16BIT_CH_0(0x106, 0x108, 0x10a, 0x10c, 0x10e, 0x120, 0x122),
[RZ_MTU3_CHAN_1] = MTU_16BIT_CH_1_2(0x186, 0x188, 0x18a),
[RZ_MTU3_CHAN_2] = MTU_16BIT_CH_1_2(0x206, 0x208, 0x20a),
[RZ_MTU3_CHAN_3] = MTU_16BIT_CH_3_6(0x010, 0x018, 0x01a, 0x024, 0x026, 0x072),
[RZ_MTU3_CHAN_4] = MTU_16BIT_CH_4_7(0x012, 0x01c, 0x01e, 0x028, 0x2a, 0x074, 0x076, 0x040, 0x044, 0x046, 0x048, 0x04a),
[RZ_MTU3_CHAN_5] = MTU_16BIT_CH_5(0xa80, 0xa82, 0xa90, 0xa92, 0xaa0, 0xaa2),
[RZ_MTU3_CHAN_6] = MTU_16BIT_CH_3_6(0x810, 0x818, 0x81a, 0x824, 0x826, 0x872),
[RZ_MTU3_CHAN_7] = MTU_16BIT_CH_4_7(0x812, 0x81c, 0x81e, 0x828, 0x82a, 0x874, 0x876, 0x840, 0x844, 0x846, 0x848, 0x84a)
};
static const unsigned long rz_mtu3_32bit_ch_reg_offs[][5] = {
[RZ_MTU3_CHAN_1] = MTU_32BIT_CH_1(0x1a0, 0x1a4, 0x1a8),
[RZ_MTU3_CHAN_8] = MTU_32BIT_CH_8(0x408, 0x40c, 0x410, 0x414, 0x418)
};
static bool rz_mtu3_is_16bit_shared_reg(u16 offset)
{
return (offset == RZ_MTU3_TDDRA || offset == RZ_MTU3_TDDRB ||
offset == RZ_MTU3_TCDRA || offset == RZ_MTU3_TCDRB ||
offset == RZ_MTU3_TCBRA || offset == RZ_MTU3_TCBRB ||
offset == RZ_MTU3_TCNTSA || offset == RZ_MTU3_TCNTSB);
}
u16 rz_mtu3_shared_reg_read(struct rz_mtu3_channel *ch, u16 offset)
{
struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
struct rz_mtu3_priv *priv = mtu->priv_data;
if (rz_mtu3_is_16bit_shared_reg(offset))
return readw(priv->mmio + offset);
else
return readb(priv->mmio + offset);
}
EXPORT_SYMBOL_GPL(rz_mtu3_shared_reg_read);
u8 rz_mtu3_8bit_ch_read(struct rz_mtu3_channel *ch, u16 offset)
{
struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
struct rz_mtu3_priv *priv = mtu->priv_data;
u16 ch_offs;
ch_offs = rz_mtu3_8bit_ch_reg_offs[ch->channel_number][offset];
return readb(priv->mmio + ch_offs);
}
EXPORT_SYMBOL_GPL(rz_mtu3_8bit_ch_read);
u16 rz_mtu3_16bit_ch_read(struct rz_mtu3_channel *ch, u16 offset)
{
struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
struct rz_mtu3_priv *priv = mtu->priv_data;
u16 ch_offs;
/* MTU8 doesn't have 16-bit registers */
if (ch->channel_number == RZ_MTU3_CHAN_8)
return 0;
ch_offs = rz_mtu3_16bit_ch_reg_offs[ch->channel_number][offset];
return readw(priv->mmio + ch_offs);
}
EXPORT_SYMBOL_GPL(rz_mtu3_16bit_ch_read);
u32 rz_mtu3_32bit_ch_read(struct rz_mtu3_channel *ch, u16 offset)
{
struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
struct rz_mtu3_priv *priv = mtu->priv_data;
u16 ch_offs;
if (ch->channel_number != RZ_MTU3_CHAN_1 && ch->channel_number != RZ_MTU3_CHAN_8)
return 0;
ch_offs = rz_mtu3_32bit_ch_reg_offs[ch->channel_number][offset];
return readl(priv->mmio + ch_offs);
}
EXPORT_SYMBOL_GPL(rz_mtu3_32bit_ch_read);
void rz_mtu3_8bit_ch_write(struct rz_mtu3_channel *ch, u16 offset, u8 val)
{
struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
struct rz_mtu3_priv *priv = mtu->priv_data;
u16 ch_offs;
ch_offs = rz_mtu3_8bit_ch_reg_offs[ch->channel_number][offset];
writeb(val, priv->mmio + ch_offs);
}
EXPORT_SYMBOL_GPL(rz_mtu3_8bit_ch_write);
void rz_mtu3_16bit_ch_write(struct rz_mtu3_channel *ch, u16 offset, u16 val)
{
struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
struct rz_mtu3_priv *priv = mtu->priv_data;
u16 ch_offs;
/* MTU8 doesn't have 16-bit registers */
if (ch->channel_number == RZ_MTU3_CHAN_8)
return;
ch_offs = rz_mtu3_16bit_ch_reg_offs[ch->channel_number][offset];
writew(val, priv->mmio + ch_offs);
}
EXPORT_SYMBOL_GPL(rz_mtu3_16bit_ch_write);
void rz_mtu3_32bit_ch_write(struct rz_mtu3_channel *ch, u16 offset, u32 val)
{
struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
struct rz_mtu3_priv *priv = mtu->priv_data;
u16 ch_offs;
if (ch->channel_number != RZ_MTU3_CHAN_1 && ch->channel_number != RZ_MTU3_CHAN_8)
return;
ch_offs = rz_mtu3_32bit_ch_reg_offs[ch->channel_number][offset];
writel(val, priv->mmio + ch_offs);
}
EXPORT_SYMBOL_GPL(rz_mtu3_32bit_ch_write);
void rz_mtu3_shared_reg_write(struct rz_mtu3_channel *ch, u16 offset, u16 value)
{
struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
struct rz_mtu3_priv *priv = mtu->priv_data;
if (rz_mtu3_is_16bit_shared_reg(offset))
writew(value, priv->mmio + offset);
else
writeb((u8)value, priv->mmio + offset);
}
EXPORT_SYMBOL_GPL(rz_mtu3_shared_reg_write);
void rz_mtu3_shared_reg_update_bit(struct rz_mtu3_channel *ch, u16 offset,
u16 pos, u8 val)
{
struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
struct rz_mtu3_priv *priv = mtu->priv_data;
unsigned long tmdr, flags;
raw_spin_lock_irqsave(&priv->lock, flags);
tmdr = rz_mtu3_shared_reg_read(ch, offset);
__assign_bit(pos, &tmdr, !!val);
rz_mtu3_shared_reg_write(ch, offset, tmdr);
raw_spin_unlock_irqrestore(&priv->lock, flags);
}
EXPORT_SYMBOL_GPL(rz_mtu3_shared_reg_update_bit);
static u16 rz_mtu3_get_tstr_offset(struct rz_mtu3_channel *ch)
{
u16 offset;
switch (ch->channel_number) {
case RZ_MTU3_CHAN_0:
case RZ_MTU3_CHAN_1:
case RZ_MTU3_CHAN_2:
case RZ_MTU3_CHAN_3:
case RZ_MTU3_CHAN_4:
case RZ_MTU3_CHAN_8:
offset = RZ_MTU3_TSTRA;
break;
case RZ_MTU3_CHAN_5:
offset = RZ_MTU3_TSTR;
break;
case RZ_MTU3_CHAN_6:
case RZ_MTU3_CHAN_7:
offset = RZ_MTU3_TSTRB;
break;
default:
offset = 0;
break;
}
return offset;
}
static u8 rz_mtu3_get_tstr_bit_pos(struct rz_mtu3_channel *ch)
{
u8 bitpos;
switch (ch->channel_number) {
case RZ_MTU3_CHAN_0:
case RZ_MTU3_CHAN_1:
case RZ_MTU3_CHAN_2:
case RZ_MTU3_CHAN_6:
case RZ_MTU3_CHAN_7:
bitpos = ch->channel_number;
break;
case RZ_MTU3_CHAN_3:
bitpos = 6;
break;
case RZ_MTU3_CHAN_4:
bitpos = 7;
break;
case RZ_MTU3_CHAN_5:
bitpos = 2;
break;
case RZ_MTU3_CHAN_8:
bitpos = 3;
break;
default:
bitpos = 0;
break;
}
return bitpos;
}
static void rz_mtu3_start_stop_ch(struct rz_mtu3_channel *ch, bool start)
{
struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
struct rz_mtu3_priv *priv = mtu->priv_data;
unsigned long flags, tstr;
u16 offset;
u8 bitpos;
/* start stop register shared by multiple timer channels */
raw_spin_lock_irqsave(&priv->lock, flags);
offset = rz_mtu3_get_tstr_offset(ch);
bitpos = rz_mtu3_get_tstr_bit_pos(ch);
tstr = rz_mtu3_shared_reg_read(ch, offset);
__assign_bit(bitpos, &tstr, start);
rz_mtu3_shared_reg_write(ch, offset, tstr);
raw_spin_unlock_irqrestore(&priv->lock, flags);
}
bool rz_mtu3_is_enabled(struct rz_mtu3_channel *ch)
{
struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
struct rz_mtu3_priv *priv = mtu->priv_data;
unsigned long flags, tstr;
bool ret = false;
u16 offset;
u8 bitpos;
/* start stop register shared by multiple timer channels */
raw_spin_lock_irqsave(&priv->lock, flags);
offset = rz_mtu3_get_tstr_offset(ch);
bitpos = rz_mtu3_get_tstr_bit_pos(ch);
tstr = rz_mtu3_shared_reg_read(ch, offset);
ret = tstr & BIT(bitpos);
raw_spin_unlock_irqrestore(&priv->lock, flags);
return ret;
}
EXPORT_SYMBOL_GPL(rz_mtu3_is_enabled);
int rz_mtu3_enable(struct rz_mtu3_channel *ch)
{
/* enable channel */
rz_mtu3_start_stop_ch(ch, true);
return 0;
}
EXPORT_SYMBOL_GPL(rz_mtu3_enable);
void rz_mtu3_disable(struct rz_mtu3_channel *ch)
{
/* disable channel */
rz_mtu3_start_stop_ch(ch, false);
}
EXPORT_SYMBOL_GPL(rz_mtu3_disable);
static void rz_mtu3_reset_assert(void *data)
{
struct rz_mtu3 *mtu = dev_get_drvdata(data);
struct rz_mtu3_priv *priv = mtu->priv_data;
mfd_remove_devices(data);
reset_control_assert(priv->rstc);
}
static const struct mfd_cell rz_mtu3_devs[] = {
{
.name = "rz-mtu3-counter",
},
{
.name = "pwm-rz-mtu3",
},
};
static int rz_mtu3_probe(struct platform_device *pdev)
{
struct rz_mtu3_priv *priv;
struct rz_mtu3 *ddata;
unsigned int i;
int ret;
ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
if (!ddata)
return -ENOMEM;
ddata->priv_data = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!ddata->priv_data)
return -ENOMEM;
priv = ddata->priv_data;
priv->mmio = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->mmio))
return PTR_ERR(priv->mmio);
priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
if (IS_ERR(priv->rstc))
return PTR_ERR(priv->rstc);
ddata->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(ddata->clk))
return PTR_ERR(ddata->clk);
reset_control_deassert(priv->rstc);
raw_spin_lock_init(&priv->lock);
platform_set_drvdata(pdev, ddata);
for (i = 0; i < RZ_MTU_NUM_CHANNELS; i++) {
ddata->channels[i].channel_number = i;
ddata->channels[i].is_busy = false;
mutex_init(&ddata->channels[i].lock);
}
ret = mfd_add_devices(&pdev->dev, 0, rz_mtu3_devs,
ARRAY_SIZE(rz_mtu3_devs), NULL, 0, NULL);
if (ret < 0)
goto err_assert;
return devm_add_action_or_reset(&pdev->dev, rz_mtu3_reset_assert,
&pdev->dev);
err_assert:
reset_control_assert(priv->rstc);
return ret;
}
static const struct of_device_id rz_mtu3_of_match[] = {
{ .compatible = "renesas,rz-mtu3", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, rz_mtu3_of_match);
static struct platform_driver rz_mtu3_driver = {
.probe = rz_mtu3_probe,
.driver = {
.name = "rz-mtu3",
.of_match_table = rz_mtu3_of_match,
},
};
module_platform_driver(rz_mtu3_driver);
MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
MODULE_DESCRIPTION("Renesas RZ/G2L MTU3a Core Driver");
MODULE_LICENSE("GPL");
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* MFD internals for Renesas RZ/G2L MTU3 Core driver
*
* Copyright (C) 2023 Renesas Electronics Corporation
*/
#ifndef RZ_MTU3_MFD_H
#define RZ_MTU3_MFD_H
#define MTU_8BIT_CH_0(_tier, _nfcr, _tcr, _tcr2, _tmdr1, _tiorh, _tiorl, _tbtm) \
{ \
[RZ_MTU3_TIER] = _tier, \
[RZ_MTU3_NFCR] = _nfcr, \
[RZ_MTU3_TCR] = _tcr, \
[RZ_MTU3_TCR2] = _tcr2, \
[RZ_MTU3_TMDR1] = _tmdr1, \
[RZ_MTU3_TIORH] = _tiorh, \
[RZ_MTU3_TIORL] = _tiorl, \
[RZ_MTU3_TBTM] = _tbtm \
}
#define MTU_8BIT_CH_1_2(_tier, _nfcr, _tsr, _tcr, _tcr2, _tmdr1, _tior) \
{ \
[RZ_MTU3_TIER] = _tier, \
[RZ_MTU3_NFCR] = _nfcr, \
[RZ_MTU3_TSR] = _tsr, \
[RZ_MTU3_TCR] = _tcr, \
[RZ_MTU3_TCR2] = _tcr2, \
[RZ_MTU3_TMDR1] = _tmdr1, \
[RZ_MTU3_TIOR] = _tior \
} \
#define MTU_8BIT_CH_3_4_6_7(_tier, _nfcr, _tsr, _tcr, _tcr2, _tmdr1, _tiorh, _tiorl, _tbtm) \
{ \
[RZ_MTU3_TIER] = _tier, \
[RZ_MTU3_NFCR] = _nfcr, \
[RZ_MTU3_TSR] = _tsr, \
[RZ_MTU3_TCR] = _tcr, \
[RZ_MTU3_TCR2] = _tcr2, \
[RZ_MTU3_TMDR1] = _tmdr1, \
[RZ_MTU3_TIORH] = _tiorh, \
[RZ_MTU3_TIORL] = _tiorl, \
[RZ_MTU3_TBTM] = _tbtm \
} \
#define MTU_8BIT_CH_5(_tier, _nfcr, _tstr, _tcntcmpclr, _tcru, _tcr2u, _tioru, \
_tcrv, _tcr2v, _tiorv, _tcrw, _tcr2w, _tiorw) \
{ \
[RZ_MTU3_TIER] = _tier, \
[RZ_MTU3_NFCR] = _nfcr, \
[RZ_MTU3_TSTR] = _tstr, \
[RZ_MTU3_TCNTCMPCLR] = _tcntcmpclr, \
[RZ_MTU3_TCRU] = _tcru, \
[RZ_MTU3_TCR2U] = _tcr2u, \
[RZ_MTU3_TIORU] = _tioru, \
[RZ_MTU3_TCRV] = _tcrv, \
[RZ_MTU3_TCR2V] = _tcr2v, \
[RZ_MTU3_TIORV] = _tiorv, \
[RZ_MTU3_TCRW] = _tcrw, \
[RZ_MTU3_TCR2W] = _tcr2w, \
[RZ_MTU3_TIORW] = _tiorw \
} \
#define MTU_8BIT_CH_8(_tier, _nfcr, _tcr, _tcr2, _tmdr1, _tiorh, _tiorl) \
{ \
[RZ_MTU3_TIER] = _tier, \
[RZ_MTU3_NFCR] = _nfcr, \
[RZ_MTU3_TCR] = _tcr, \
[RZ_MTU3_TCR2] = _tcr2, \
[RZ_MTU3_TMDR1] = _tmdr1, \
[RZ_MTU3_TIORH] = _tiorh, \
[RZ_MTU3_TIORL] = _tiorl \
} \
#define MTU_16BIT_CH_0(_tcnt, _tgra, _tgrb, _tgrc, _tgrd, _tgre, _tgrf) \
{ \
[RZ_MTU3_TCNT] = _tcnt, \
[RZ_MTU3_TGRA] = _tgra, \
[RZ_MTU3_TGRB] = _tgrb, \
[RZ_MTU3_TGRC] = _tgrc, \
[RZ_MTU3_TGRD] = _tgrd, \
[RZ_MTU3_TGRE] = _tgre, \
[RZ_MTU3_TGRF] = _tgrf \
}
#define MTU_16BIT_CH_1_2(_tcnt, _tgra, _tgrb) \
{ \
[RZ_MTU3_TCNT] = _tcnt, \
[RZ_MTU3_TGRA] = _tgra, \
[RZ_MTU3_TGRB] = _tgrb \
}
#define MTU_16BIT_CH_3_6(_tcnt, _tgra, _tgrb, _tgrc, _tgrd, _tgre) \
{ \
[RZ_MTU3_TCNT] = _tcnt, \
[RZ_MTU3_TGRA] = _tgra, \
[RZ_MTU3_TGRB] = _tgrb, \
[RZ_MTU3_TGRC] = _tgrc, \
[RZ_MTU3_TGRD] = _tgrd, \
[RZ_MTU3_TGRE] = _tgre \
}
#define MTU_16BIT_CH_4_7(_tcnt, _tgra, _tgrb, _tgrc, _tgrd, _tgre, _tgrf, \
_tadcr, _tadcora, _tadcorb, _tadcobra, _tadcobrb) \
{ \
[RZ_MTU3_TCNT] = _tcnt, \
[RZ_MTU3_TGRA] = _tgra, \
[RZ_MTU3_TGRB] = _tgrb, \
[RZ_MTU3_TGRC] = _tgrc, \
[RZ_MTU3_TGRD] = _tgrd, \
[RZ_MTU3_TGRE] = _tgre, \
[RZ_MTU3_TGRF] = _tgrf, \
[RZ_MTU3_TADCR] = _tadcr, \
[RZ_MTU3_TADCORA] = _tadcora, \
[RZ_MTU3_TADCORB] = _tadcorb, \
[RZ_MTU3_TADCOBRA] = _tadcobra, \
[RZ_MTU3_TADCOBRB] = _tadcobrb \
}
#define MTU_16BIT_CH_5(_tcntu, _tgru, _tcntv, _tgrv, _tcntw, _tgrw) \
{ \
[RZ_MTU3_TCNTU] = _tcntu, \
[RZ_MTU3_TGRU] = _tgru, \
[RZ_MTU3_TCNTV] = _tcntv, \
[RZ_MTU3_TGRV] = _tgrv, \
[RZ_MTU3_TCNTW] = _tcntw, \
[RZ_MTU3_TGRW] = _tgrw \
}
#define MTU_32BIT_CH_1(_tcntlw, _tgralw, _tgrblw) \
{ \
[RZ_MTU3_TCNTLW] = _tcntlw, \
[RZ_MTU3_TGRALW] = _tgralw, \
[RZ_MTU3_TGRBLW] = _tgrblw \
}
#define MTU_32BIT_CH_8(_tcnt, _tgra, _tgrb, _tgrc, _tgrd) \
{ \
[RZ_MTU3_TCNT] = _tcnt, \
[RZ_MTU3_TGRA] = _tgra, \
[RZ_MTU3_TGRB] = _tgrb, \
[RZ_MTU3_TGRC] = _tgrc, \
[RZ_MTU3_TGRD] = _tgrd \
}
#endif
......@@ -24,22 +24,9 @@
#include <linux/mfd/samsung/s2mps14.h>
#include <linux/mfd/samsung/s2mps15.h>
#include <linux/mfd/samsung/s2mpu02.h>
#include <linux/mfd/samsung/s5m8763.h>
#include <linux/mfd/samsung/s5m8767.h>
#include <linux/regmap.h>
static const struct mfd_cell s5m8751_devs[] = {
{ .name = "s5m8751-pmic", },
{ .name = "s5m-charger", },
{ .name = "s5m8751-codec", },
};
static const struct mfd_cell s5m8763_devs[] = {
{ .name = "s5m8763-pmic", },
{ .name = "s5m-rtc", },
{ .name = "s5m-charger", },
};
static const struct mfd_cell s5m8767_devs[] = {
{ .name = "s5m8767-pmic", },
{ .name = "s5m-rtc", },
......@@ -158,19 +145,6 @@ static bool s2mpu02_volatile(struct device *dev, unsigned int reg)
}
}
static bool s5m8763_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
case S5M8763_REG_IRQM1:
case S5M8763_REG_IRQM2:
case S5M8763_REG_IRQM3:
case S5M8763_REG_IRQM4:
return false;
default:
return true;
}
}
static const struct regmap_config sec_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
......@@ -230,15 +204,6 @@ static const struct regmap_config s2mpu02_regmap_config = {
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config s5m8763_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S5M8763_REG_LBCNFG2,
.volatile_reg = s5m8763_volatile,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config s5m8767_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
......@@ -348,9 +313,6 @@ static int sec_pmic_probe(struct i2c_client *i2c)
case S2MPS15X:
regmap = &s2mps15_regmap_config;
break;
case S5M8763X:
regmap = &s5m8763_regmap_config;
break;
case S5M8767X:
regmap = &s5m8767_regmap_config;
break;
......@@ -375,14 +337,6 @@ static int sec_pmic_probe(struct i2c_client *i2c)
pm_runtime_set_active(sec_pmic->dev);
switch (sec_pmic->device_type) {
case S5M8751X:
sec_devs = s5m8751_devs;
num_sec_devs = ARRAY_SIZE(s5m8751_devs);
break;
case S5M8763X:
sec_devs = s5m8763_devs;
num_sec_devs = ARRAY_SIZE(s5m8763_devs);
break;
case S5M8767X:
sec_devs = s5m8767_devs;
num_sec_devs = ARRAY_SIZE(s5m8767_devs);
......
......@@ -14,7 +14,6 @@
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps14.h>
#include <linux/mfd/samsung/s2mpu02.h>
#include <linux/mfd/samsung/s5m8763.h>
#include <linux/mfd/samsung/s5m8767.h>
static const struct regmap_irq s2mps11_irqs[] = {
......@@ -297,81 +296,6 @@ static const struct regmap_irq s5m8767_irqs[] = {
},
};
static const struct regmap_irq s5m8763_irqs[] = {
[S5M8763_IRQ_DCINF] = {
.reg_offset = 0,
.mask = S5M8763_IRQ_DCINF_MASK,
},
[S5M8763_IRQ_DCINR] = {
.reg_offset = 0,
.mask = S5M8763_IRQ_DCINR_MASK,
},
[S5M8763_IRQ_JIGF] = {
.reg_offset = 0,
.mask = S5M8763_IRQ_JIGF_MASK,
},
[S5M8763_IRQ_JIGR] = {
.reg_offset = 0,
.mask = S5M8763_IRQ_JIGR_MASK,
},
[S5M8763_IRQ_PWRONF] = {
.reg_offset = 0,
.mask = S5M8763_IRQ_PWRONF_MASK,
},
[S5M8763_IRQ_PWRONR] = {
.reg_offset = 0,
.mask = S5M8763_IRQ_PWRONR_MASK,
},
[S5M8763_IRQ_WTSREVNT] = {
.reg_offset = 1,
.mask = S5M8763_IRQ_WTSREVNT_MASK,
},
[S5M8763_IRQ_SMPLEVNT] = {
.reg_offset = 1,
.mask = S5M8763_IRQ_SMPLEVNT_MASK,
},
[S5M8763_IRQ_ALARM1] = {
.reg_offset = 1,
.mask = S5M8763_IRQ_ALARM1_MASK,
},
[S5M8763_IRQ_ALARM0] = {
.reg_offset = 1,
.mask = S5M8763_IRQ_ALARM0_MASK,
},
[S5M8763_IRQ_ONKEY1S] = {
.reg_offset = 2,
.mask = S5M8763_IRQ_ONKEY1S_MASK,
},
[S5M8763_IRQ_TOPOFFR] = {
.reg_offset = 2,
.mask = S5M8763_IRQ_TOPOFFR_MASK,
},
[S5M8763_IRQ_DCINOVPR] = {
.reg_offset = 2,
.mask = S5M8763_IRQ_DCINOVPR_MASK,
},
[S5M8763_IRQ_CHGRSTF] = {
.reg_offset = 2,
.mask = S5M8763_IRQ_CHGRSTF_MASK,
},
[S5M8763_IRQ_DONER] = {
.reg_offset = 2,
.mask = S5M8763_IRQ_DONER_MASK,
},
[S5M8763_IRQ_CHGFAULT] = {
.reg_offset = 2,
.mask = S5M8763_IRQ_CHGFAULT_MASK,
},
[S5M8763_IRQ_LOBAT1] = {
.reg_offset = 3,
.mask = S5M8763_IRQ_LOBAT1_MASK,
},
[S5M8763_IRQ_LOBAT2] = {
.reg_offset = 3,
.mask = S5M8763_IRQ_LOBAT2_MASK,
},
};
static const struct regmap_irq_chip s2mps11_irq_chip = {
.name = "s2mps11",
.irqs = s2mps11_irqs,
......@@ -425,16 +349,6 @@ static const struct regmap_irq_chip s5m8767_irq_chip = {
.ack_base = S5M8767_REG_INT1,
};
static const struct regmap_irq_chip s5m8763_irq_chip = {
.name = "s5m8763",
.irqs = s5m8763_irqs,
.num_irqs = ARRAY_SIZE(s5m8763_irqs),
.num_regs = 4,
.status_base = S5M8763_REG_IRQ1,
.mask_base = S5M8763_REG_IRQM1,
.ack_base = S5M8763_REG_IRQ1,
};
int sec_irq_init(struct sec_pmic_dev *sec_pmic)
{
int ret = 0;
......@@ -448,9 +362,6 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
}
switch (type) {
case S5M8763X:
sec_irq_chip = &s5m8763_irq_chip;
break;
case S5M8767X:
sec_irq_chip = &s5m8767_irq_chip;
break;
......
......@@ -251,7 +251,7 @@ static int si476x_core_parse_and_nag_about_error(struct si476x_core *core)
* @usecs: amount of time to wait before reading the response (in
* usecs)
*
* Function returns 0 on succsess and negative error code on
* Function returns 0 on success and negative error code on
* failure
*/
static int si476x_core_send_command(struct si476x_core *core,
......@@ -398,7 +398,7 @@ static int si476x_cmd_tune_seek_freq(struct si476x_core *core,
* The command requests the firmware and patch version for currently
* loaded firmware (dependent on the function of the device FM/AM/WB)
*
* Function returns 0 on succsess and negative error code on
* Function returns 0 on success and negative error code on
* failure
*/
int si476x_core_cmd_func_info(struct si476x_core *core,
......@@ -429,7 +429,7 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_func_info);
* @property: property address
* @value: property value
*
* Function returns 0 on succsess and negative error code on
* Function returns 0 on success and negative error code on
* failure
*/
int si476x_core_cmd_set_property(struct si476x_core *core,
......@@ -545,13 +545,13 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_dig_audio_pin_cfg);
* SI476X_IQCLK_NOOP - do not modify the behaviour
* SI476X_IQCLK_TRISTATE - put the pin in tristate condition,
* enable 1MOhm pulldown
* SI476X_IQCLK_IQ - set pin to be a part of I/Q interace
* SI476X_IQCLK_IQ - set pin to be a part of I/Q interface
* in master mode
* @iqfs: - IQFS pin function configuration:
* SI476X_IQFS_NOOP - do not modify the behaviour
* SI476X_IQFS_TRISTATE - put the pin in tristate condition,
* enable 1MOhm pulldown
* SI476X_IQFS_IQ - set pin to be a part of I/Q interace
* SI476X_IQFS_IQ - set pin to be a part of I/Q interface
* in master mode
* @iout: - IOUT pin function configuration:
* SI476X_IOUT_NOOP - do not modify the behaviour
......@@ -589,7 +589,7 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_zif_pin_cfg);
/**
* si476x_core_cmd_ic_link_gpo_ctl_pin_cfg - send
* 'IC_LINK_GPIO_CTL_PIN_CFG' comand to the device
* 'IC_LINK_GPIO_CTL_PIN_CFG' command to the device
* @core: - device to send the command to
* @icin: - ICIN pin function configuration:
* SI476X_ICIN_NOOP - do not modify the behaviour
......@@ -1014,7 +1014,7 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_phase_diversity);
* NOTE caller must hold core lock
*
* Function returns the value of the status bit in case of success and
* negative error code in case of failre.
* negative error code in case of failure.
*/
int si476x_core_cmd_fm_phase_div_status(struct si476x_core *core)
{
......
......@@ -72,9 +72,22 @@ static const struct simple_mfd_data silergy_sy7636a = {
.mfd_cell_size = ARRAY_SIZE(sy7636a_cells),
};
static const struct mfd_cell max597x_cells[] = {
{ .name = "max597x-regulator", },
{ .name = "max597x-iio", },
{ .name = "max597x-led", },
};
static const struct simple_mfd_data maxim_max597x = {
.mfd_cell = max597x_cells,
.mfd_cell_size = ARRAY_SIZE(max597x_cells),
};
static const struct of_device_id simple_mfd_i2c_of_match[] = {
{ .compatible = "kontron,sl28cpld" },
{ .compatible = "silergy,sy7636a", .data = &silergy_sy7636a},
{ .compatible = "maxim,max5970", .data = &maxim_max597x},
{ .compatible = "maxim,max5978", .data = &maxim_max597x},
{}
};
MODULE_DEVICE_TABLE(of, simple_mfd_i2c_of_match);
......
......@@ -262,7 +262,6 @@ EXPORT_SYMBOL_GPL(ssbi_write);
static int ssbi_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct resource *mem_res;
struct ssbi *ssbi;
const char *type;
......@@ -270,8 +269,7 @@ static int ssbi_probe(struct platform_device *pdev)
if (!ssbi)
return -ENOMEM;
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ssbi->base = devm_ioremap_resource(&pdev->dev, mem_res);
ssbi->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(ssbi->base))
return PTR_ERR(ssbi->base);
......
......@@ -135,6 +135,5 @@ static void __exit stmpe_exit(void)
}
module_exit(stmpe_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("STMPE MFD I2C Interface Driver");
MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>");
......@@ -154,6 +154,5 @@ static void __exit stmpe_exit(void)
}
module_exit(stmpe_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("STMPE MFD SPI Interface Driver");
MODULE_AUTHOR("Viresh Kumar <vireshk@kernel.org>");
......@@ -1378,7 +1378,7 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum)
stmpe_of_probe(pdata, np);
if (of_find_property(np, "interrupts", NULL) == NULL)
if (!of_property_present(np, "interrupts"))
ci->irq = -1;
stmpe = devm_kzalloc(ci->dev, sizeof(struct stmpe), GFP_KERNEL);
......
......@@ -93,7 +93,6 @@ MODULE_DEVICE_TABLE(of, sun4i_gpadc_of_match);
static int sun4i_gpadc_probe(struct platform_device *pdev)
{
struct sun4i_gpadc_dev *dev;
struct resource *mem;
const struct of_device_id *of_id;
const struct mfd_cell *cells;
unsigned int irq, size;
......@@ -124,8 +123,7 @@ static int sun4i_gpadc_probe(struct platform_device *pdev)
if (!dev)
return -ENOMEM;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dev->base = devm_ioremap_resource(&pdev->dev, mem);
dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(dev->base))
return PTR_ERR(dev->base);
......
......@@ -502,6 +502,5 @@ static void __exit tc3589x_exit(void)
}
module_exit(tc3589x_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("TC3589x MFD core driver");
MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
......@@ -638,4 +638,3 @@ module_exit(tps6586x_exit);
MODULE_DESCRIPTION("TPS6586X core driver");
MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
MODULE_LICENSE("GPL");
......@@ -16,8 +16,8 @@
#include <linux/platform_data/i2c-ocores.h>
#include <linux/platform_device.h>
#define TQMX86_IOBASE 0x160
#define TQMX86_IOSIZE 0x3f
#define TQMX86_IOBASE 0x180
#define TQMX86_IOSIZE 0x20
#define TQMX86_IOBASE_I2C 0x1a0
#define TQMX86_IOSIZE_I2C 0xa
#define TQMX86_IOBASE_WATCHDOG 0x18b
......@@ -25,14 +25,14 @@
#define TQMX86_IOBASE_GPIO 0x18d
#define TQMX86_IOSIZE_GPIO 0x4
#define TQMX86_REG_BOARD_ID 0x20
#define TQMX86_REG_BOARD_ID 0x00
#define TQMX86_REG_BOARD_ID_E38M 1
#define TQMX86_REG_BOARD_ID_50UC 2
#define TQMX86_REG_BOARD_ID_E38C 3
#define TQMX86_REG_BOARD_ID_60EB 4
#define TQMX86_REG_BOARD_ID_E39M 5
#define TQMX86_REG_BOARD_ID_E39C 6
#define TQMX86_REG_BOARD_ID_E39x 7
#define TQMX86_REG_BOARD_ID_E39MS 5
#define TQMX86_REG_BOARD_ID_E39C1 6
#define TQMX86_REG_BOARD_ID_E39C2 7
#define TQMX86_REG_BOARD_ID_70EB 8
#define TQMX86_REG_BOARD_ID_80UC 9
#define TQMX86_REG_BOARD_ID_110EB 11
......@@ -40,18 +40,18 @@
#define TQMX86_REG_BOARD_ID_E40S 13
#define TQMX86_REG_BOARD_ID_E40C1 14
#define TQMX86_REG_BOARD_ID_E40C2 15
#define TQMX86_REG_BOARD_REV 0x21
#define TQMX86_REG_IO_EXT_INT 0x26
#define TQMX86_REG_BOARD_REV 0x01
#define TQMX86_REG_IO_EXT_INT 0x06
#define TQMX86_REG_IO_EXT_INT_NONE 0
#define TQMX86_REG_IO_EXT_INT_7 1
#define TQMX86_REG_IO_EXT_INT_9 2
#define TQMX86_REG_IO_EXT_INT_12 3
#define TQMX86_REG_IO_EXT_INT_MASK 0x3
#define TQMX86_REG_IO_EXT_INT_GPIO_SHIFT 4
#define TQMX86_REG_SAUC 0x17
#define TQMX86_REG_I2C_DETECT 0x47
#define TQMX86_REG_I2C_DETECT 0x1a7
#define TQMX86_REG_I2C_DETECT_SOFT 0xa5
#define TQMX86_REG_I2C_INT_EN 0x49
static uint gpio_irq;
module_param(gpio_irq, uint, 0);
......@@ -111,7 +111,7 @@ static const struct mfd_cell tqmx86_devs[] = {
},
};
static const char *tqmx86_board_id_to_name(u8 board_id)
static const char *tqmx86_board_id_to_name(u8 board_id, u8 sauc)
{
switch (board_id) {
case TQMX86_REG_BOARD_ID_E38M:
......@@ -122,12 +122,12 @@ static const char *tqmx86_board_id_to_name(u8 board_id)
return "TQMxE38C";
case TQMX86_REG_BOARD_ID_60EB:
return "TQMx60EB";
case TQMX86_REG_BOARD_ID_E39M:
return "TQMxE39M";
case TQMX86_REG_BOARD_ID_E39C:
return "TQMxE39C";
case TQMX86_REG_BOARD_ID_E39x:
return "TQMxE39x";
case TQMX86_REG_BOARD_ID_E39MS:
return (sauc == 0xff) ? "TQMxE39M" : "TQMxE39S";
case TQMX86_REG_BOARD_ID_E39C1:
return "TQMxE39C1";
case TQMX86_REG_BOARD_ID_E39C2:
return "TQMxE39C2";
case TQMX86_REG_BOARD_ID_70EB:
return "TQMx70EB";
case TQMX86_REG_BOARD_ID_80UC:
......@@ -160,9 +160,9 @@ static int tqmx86_board_id_to_clk_rate(struct device *dev, u8 board_id)
case TQMX86_REG_BOARD_ID_E40C1:
case TQMX86_REG_BOARD_ID_E40C2:
return 24000;
case TQMX86_REG_BOARD_ID_E39M:
case TQMX86_REG_BOARD_ID_E39C:
case TQMX86_REG_BOARD_ID_E39x:
case TQMX86_REG_BOARD_ID_E39MS:
case TQMX86_REG_BOARD_ID_E39C1:
case TQMX86_REG_BOARD_ID_E39C2:
return 25000;
case TQMX86_REG_BOARD_ID_E38M:
case TQMX86_REG_BOARD_ID_E38C:
......@@ -176,7 +176,7 @@ static int tqmx86_board_id_to_clk_rate(struct device *dev, u8 board_id)
static int tqmx86_probe(struct platform_device *pdev)
{
u8 board_id, rev, i2c_det, io_ext_int_val;
u8 board_id, sauc, rev, i2c_det, io_ext_int_val;
struct device *dev = &pdev->dev;
u8 gpio_irq_cfg, readback;
const char *board_name;
......@@ -206,14 +206,20 @@ static int tqmx86_probe(struct platform_device *pdev)
return -ENOMEM;
board_id = ioread8(io_base + TQMX86_REG_BOARD_ID);
board_name = tqmx86_board_id_to_name(board_id);
sauc = ioread8(io_base + TQMX86_REG_SAUC);
board_name = tqmx86_board_id_to_name(board_id, sauc);
rev = ioread8(io_base + TQMX86_REG_BOARD_REV);
dev_info(dev,
"Found %s - Board ID %d, PCB Revision %d, PLD Revision %d\n",
board_name, board_id, rev >> 4, rev & 0xf);
i2c_det = ioread8(io_base + TQMX86_REG_I2C_DETECT);
/*
* The I2C_DETECT register is in the range assigned to the I2C driver
* later, so we don't extend TQMX86_IOSIZE. Use inb() for this one-off
* access instead of ioport_map + unmap.
*/
i2c_det = inb(TQMX86_REG_I2C_DETECT);
if (gpio_irq_cfg) {
io_ext_int_val =
......
......@@ -594,71 +594,6 @@ int twl_get_hfclk_rate(void)
}
EXPORT_SYMBOL_GPL(twl_get_hfclk_rate);
static struct device *
add_numbered_child(unsigned mod_no, const char *name, int num,
void *pdata, unsigned pdata_len,
bool can_wakeup, int irq0, int irq1)
{
struct platform_device *pdev;
struct twl_client *twl;
int status, sid;
if (unlikely(mod_no >= twl_get_last_module())) {
pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
return ERR_PTR(-EPERM);
}
sid = twl_priv->twl_map[mod_no].sid;
twl = &twl_priv->twl_modules[sid];
pdev = platform_device_alloc(name, num);
if (!pdev)
return ERR_PTR(-ENOMEM);
pdev->dev.parent = &twl->client->dev;
if (pdata) {
status = platform_device_add_data(pdev, pdata, pdata_len);
if (status < 0) {
dev_dbg(&pdev->dev, "can't add platform_data\n");
goto put_device;
}
}
if (irq0) {
struct resource r[2] = {
{ .start = irq0, .flags = IORESOURCE_IRQ, },
{ .start = irq1, .flags = IORESOURCE_IRQ, },
};
status = platform_device_add_resources(pdev, r, irq1 ? 2 : 1);
if (status < 0) {
dev_dbg(&pdev->dev, "can't add irqs\n");
goto put_device;
}
}
status = platform_device_add(pdev);
if (status)
goto put_device;
device_init_wakeup(&pdev->dev, can_wakeup);
return &pdev->dev;
put_device:
platform_device_put(pdev);
dev_err(&twl->client->dev, "failed to add device %s\n", name);
return ERR_PTR(status);
}
static inline struct device *add_child(unsigned mod_no, const char *name,
void *pdata, unsigned pdata_len,
bool can_wakeup, int irq0, int irq1)
{
return add_numbered_child(mod_no, name, -1, pdata, pdata_len,
can_wakeup, irq0, irq1);
}
/*----------------------------------------------------------------------*/
/*
......
......@@ -285,5 +285,4 @@ module_platform_driver(twl4030_audio_driver);
MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
MODULE_DESCRIPTION("TWL4030 audio block MFD driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:twl4030-audio");
......@@ -839,4 +839,3 @@ module_i2c_driver(twl6040_driver);
MODULE_DESCRIPTION("TWL6040 MFD");
MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
MODULE_AUTHOR("Jorge Eduardo Candelaria <jorge.candelaria@ti.com>");
MODULE_LICENSE("GPL");
......@@ -279,20 +279,11 @@ static int wm8994_set_pdata_from_of(struct wm8994 *wm8994)
of_property_read_u32_array(np, "wlf,micbias-cfg", pdata->micbias,
ARRAY_SIZE(pdata->micbias));
pdata->lineout1_diff = true;
pdata->lineout2_diff = true;
if (of_find_property(np, "wlf,lineout1-se", NULL))
pdata->lineout1_diff = false;
if (of_find_property(np, "wlf,lineout2-se", NULL))
pdata->lineout2_diff = false;
if (of_find_property(np, "wlf,lineout1-feedback", NULL))
pdata->lineout1fb = true;
if (of_find_property(np, "wlf,lineout2-feedback", NULL))
pdata->lineout2fb = true;
if (of_find_property(np, "wlf,ldoena-always-driven", NULL))
pdata->lineout2fb = true;
pdata->lineout1_diff = !of_property_read_bool(np, "wlf,lineout1-se");
pdata->lineout2_diff = !of_property_read_bool(np, "wlf,lineout2-se");
pdata->lineout1fb = of_property_read_bool(np, "wlf,lineout1-feedback");
pdata->lineout2fb = of_property_read_bool(np, "wlf,lineout2-feedback") ||
of_property_read_bool(np, "wlf,ldoena-always-driven");
pdata->spkmode_pu = of_property_read_bool(np, "wlf,spkmode-pu");
......
......@@ -85,7 +85,7 @@ struct s5m_rtc_reg_config {
unsigned int write_alarm_udr_mask;
};
/* Register map for S5M8763 and S5M8767 */
/* Register map for S5M8767 */
static const struct s5m_rtc_reg_config s5m_rtc_regs = {
.regs_count = 8,
.time = S5M_RTC_SEC,
......@@ -236,7 +236,6 @@ static int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info,
switch (info->device_type) {
case S5M8767X:
case S5M8763X:
ret = regmap_read(info->regmap, S5M_RTC_STATUS, &val);
val &= S5M_ALARM0_STATUS;
break;
......@@ -299,7 +298,6 @@ static int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
data |= info->regs->write_alarm_udr_mask;
switch (info->device_type) {
case S5M8763X:
case S5M8767X:
data &= ~S5M_RTC_TIME_EN_MASK;
break;
......@@ -329,38 +327,6 @@ static int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
return ret;
}
static void s5m8763_data_to_tm(u8 *data, struct rtc_time *tm)
{
tm->tm_sec = bcd2bin(data[RTC_SEC]);
tm->tm_min = bcd2bin(data[RTC_MIN]);
if (data[RTC_HOUR] & HOUR_12) {
tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x1f);
if (data[RTC_HOUR] & HOUR_PM)
tm->tm_hour += 12;
} else {
tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x3f);
}
tm->tm_wday = data[RTC_WEEKDAY] & 0x07;
tm->tm_mday = bcd2bin(data[RTC_DATE]);
tm->tm_mon = bcd2bin(data[RTC_MONTH]);
tm->tm_year = bcd2bin(data[RTC_YEAR1]) + bcd2bin(data[RTC_YEAR2]) * 100;
tm->tm_year -= 1900;
}
static void s5m8763_tm_to_data(struct rtc_time *tm, u8 *data)
{
data[RTC_SEC] = bin2bcd(tm->tm_sec);
data[RTC_MIN] = bin2bcd(tm->tm_min);
data[RTC_HOUR] = bin2bcd(tm->tm_hour);
data[RTC_WEEKDAY] = tm->tm_wday;
data[RTC_DATE] = bin2bcd(tm->tm_mday);
data[RTC_MONTH] = bin2bcd(tm->tm_mon);
data[RTC_YEAR1] = bin2bcd(tm->tm_year % 100);
data[RTC_YEAR2] = bin2bcd((tm->tm_year + 1900) / 100);
}
static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct s5m_rtc_info *info = dev_get_drvdata(dev);
......@@ -385,10 +351,6 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
return ret;
switch (info->device_type) {
case S5M8763X:
s5m8763_data_to_tm(data, tm);
break;
case S5M8767X:
case S2MPS15X:
case S2MPS14X:
......@@ -412,9 +374,6 @@ static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm)
int ret = 0;
switch (info->device_type) {
case S5M8763X:
s5m8763_tm_to_data(tm, data);
break;
case S5M8767X:
case S2MPS15X:
case S2MPS14X:
......@@ -444,7 +403,6 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct s5m_rtc_info *info = dev_get_drvdata(dev);
u8 data[RTC_MAX_NUM_TIME_REGS];
unsigned int val;
int ret, i;
ret = regmap_bulk_read(info->regmap, info->regs->alarm0, data,
......@@ -453,15 +411,6 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
return ret;
switch (info->device_type) {
case S5M8763X:
s5m8763_data_to_tm(data, &alrm->time);
ret = regmap_read(info->regmap, S5M_ALARM0_CONF, &val);
if (ret < 0)
return ret;
alrm->enabled = !!val;
break;
case S5M8767X:
case S2MPS15X:
case S2MPS14X:
......@@ -500,10 +449,6 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info)
dev_dbg(info->dev, "%s: %ptR(%d)\n", __func__, &tm, tm.tm_wday);
switch (info->device_type) {
case S5M8763X:
ret = regmap_write(info->regmap, S5M_ALARM0_CONF, 0);
break;
case S5M8767X:
case S2MPS15X:
case S2MPS14X:
......@@ -531,7 +476,6 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info)
{
int ret;
u8 data[RTC_MAX_NUM_TIME_REGS];
u8 alarm0_conf;
struct rtc_time tm;
ret = regmap_bulk_read(info->regmap, info->regs->alarm0, data,
......@@ -543,11 +487,6 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info)
dev_dbg(info->dev, "%s: %ptR(%d)\n", __func__, &tm, tm.tm_wday);
switch (info->device_type) {
case S5M8763X:
alarm0_conf = 0x77;
ret = regmap_write(info->regmap, S5M_ALARM0_CONF, alarm0_conf);
break;
case S5M8767X:
case S2MPS15X:
case S2MPS14X:
......@@ -585,10 +524,6 @@ static int s5m_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
int ret;
switch (info->device_type) {
case S5M8763X:
s5m8763_tm_to_data(&alrm->time, data);
break;
case S5M8767X:
case S2MPS15X:
case S2MPS14X:
......@@ -655,7 +590,6 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
int ret;
switch (info->device_type) {
case S5M8763X:
case S5M8767X:
/* UDR update time. Default of 7.32 ms is too long. */
ret = regmap_update_bits(info->regmap, S5M_RTC_UDR_CON,
......@@ -729,11 +663,6 @@ static int s5m_rtc_probe(struct platform_device *pdev)
info->regs = &s2mps13_rtc_regs;
alarm_irq = S2MPS14_IRQ_RTCA0;
break;
case S5M8763X:
regmap_cfg = &s5m_rtc_regmap_config;
info->regs = &s5m_rtc_regs;
alarm_irq = S5M8763_IRQ_ALARM0;
break;
case S5M8767X:
regmap_cfg = &s5m_rtc_regmap_config;
info->regs = &s5m_rtc_regs;
......@@ -786,13 +715,8 @@ static int s5m_rtc_probe(struct platform_device *pdev)
info->rtc_dev->ops = &s5m_rtc_ops;
if (info->device_type == S5M8763X) {
info->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_0000;
info->rtc_dev->range_max = RTC_TIMESTAMP_END_9999;
} else {
info->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
info->rtc_dev->range_max = RTC_TIMESTAMP_END_2099;
}
info->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
info->rtc_dev->range_max = RTC_TIMESTAMP_END_2099;
if (!info->irq) {
clear_bit(RTC_FEATURE_ALARM, info->rtc_dev->features);
......
......@@ -34,7 +34,6 @@
#define STM32F4_AHB1_RESET(bit) (STM32F4_RCC_AHB1_##bit + (0x10 * 8))
#define STM32F4_AHB1_CLOCK(bit) (STM32F4_RCC_AHB1_##bit)
/* AHB2 */
#define STM32F4_RCC_AHB2_DCMI 0
#define STM32F4_RCC_AHB2_CRYP 4
......
......@@ -21,6 +21,7 @@ enum axp20x_variants {
AXP806_ID,
AXP809_ID,
AXP813_ID,
AXP15060_ID,
NR_AXP20X_VARIANTS,
};
......@@ -131,6 +132,39 @@ enum axp20x_variants {
/* Other DCDC regulator control registers are the same as AXP803 */
#define AXP813_DCDC7_V_OUT 0x26
#define AXP15060_STARTUP_SRC 0x00
#define AXP15060_PWR_OUT_CTRL1 0x10
#define AXP15060_PWR_OUT_CTRL2 0x11
#define AXP15060_PWR_OUT_CTRL3 0x12
#define AXP15060_DCDC1_V_CTRL 0x13
#define AXP15060_DCDC2_V_CTRL 0x14
#define AXP15060_DCDC3_V_CTRL 0x15
#define AXP15060_DCDC4_V_CTRL 0x16
#define AXP15060_DCDC5_V_CTRL 0x17
#define AXP15060_DCDC6_V_CTRL 0x18
#define AXP15060_ALDO1_V_CTRL 0x19
#define AXP15060_DCDC_MODE_CTRL1 0x1a
#define AXP15060_DCDC_MODE_CTRL2 0x1b
#define AXP15060_OUTPUT_MONITOR_DISCHARGE 0x1e
#define AXP15060_IRQ_PWROK_VOFF 0x1f
#define AXP15060_ALDO2_V_CTRL 0x20
#define AXP15060_ALDO3_V_CTRL 0x21
#define AXP15060_ALDO4_V_CTRL 0x22
#define AXP15060_ALDO5_V_CTRL 0x23
#define AXP15060_BLDO1_V_CTRL 0x24
#define AXP15060_BLDO2_V_CTRL 0x25
#define AXP15060_BLDO3_V_CTRL 0x26
#define AXP15060_BLDO4_V_CTRL 0x27
#define AXP15060_BLDO5_V_CTRL 0x28
#define AXP15060_CLDO1_V_CTRL 0x29
#define AXP15060_CLDO2_V_CTRL 0x2a
#define AXP15060_CLDO3_V_CTRL 0x2b
#define AXP15060_CLDO4_V_CTRL 0x2d
#define AXP15060_CPUSLDO_V_CTRL 0x2e
#define AXP15060_PWR_WAKEUP_CTRL 0x31
#define AXP15060_PWR_DISABLE_DOWN_SEQ 0x32
#define AXP15060_PEK_KEY 0x36
/* Interrupt */
#define AXP152_IRQ1_EN 0x40
#define AXP152_IRQ2_EN 0x41
......@@ -152,6 +186,11 @@ enum axp20x_variants {
#define AXP20X_IRQ5_STATE 0x4c
#define AXP20X_IRQ6_STATE 0x4d
#define AXP15060_IRQ1_EN 0x40
#define AXP15060_IRQ2_EN 0x41
#define AXP15060_IRQ1_STATE 0x48
#define AXP15060_IRQ2_STATE 0x49
/* ADC */
#define AXP20X_ACIN_V_ADC_H 0x56
#define AXP20X_ACIN_V_ADC_L 0x57
......@@ -222,6 +261,8 @@ enum axp20x_variants {
#define AXP22X_GPIO_STATE 0x94
#define AXP22X_GPIO_PULL_DOWN 0x95
#define AXP15060_CLDO4_GPIO2_MODESET 0x2c
/* Battery */
#define AXP20X_CHRG_CC_31_24 0xb0
#define AXP20X_CHRG_CC_23_16 0xb1
......@@ -419,6 +460,33 @@ enum {
AXP813_REG_ID_MAX,
};
enum {
AXP15060_DCDC1 = 0,
AXP15060_DCDC2,
AXP15060_DCDC3,
AXP15060_DCDC4,
AXP15060_DCDC5,
AXP15060_DCDC6,
AXP15060_ALDO1,
AXP15060_ALDO2,
AXP15060_ALDO3,
AXP15060_ALDO4,
AXP15060_ALDO5,
AXP15060_BLDO1,
AXP15060_BLDO2,
AXP15060_BLDO3,
AXP15060_BLDO4,
AXP15060_BLDO5,
AXP15060_CLDO1,
AXP15060_CLDO2,
AXP15060_CLDO3,
AXP15060_CLDO4,
AXP15060_CPUSLDO,
AXP15060_SW,
AXP15060_RTC_LDO,
AXP15060_REG_ID_MAX,
};
/* IRQs */
enum {
AXP152_IRQ_LDO0IN_CONNECT = 1,
......@@ -637,6 +705,23 @@ enum axp809_irqs {
AXP809_IRQ_GPIO0_INPUT,
};
enum axp15060_irqs {
AXP15060_IRQ_DIE_TEMP_HIGH_LV1 = 1,
AXP15060_IRQ_DIE_TEMP_HIGH_LV2,
AXP15060_IRQ_DCDC1_V_LOW,
AXP15060_IRQ_DCDC2_V_LOW,
AXP15060_IRQ_DCDC3_V_LOW,
AXP15060_IRQ_DCDC4_V_LOW,
AXP15060_IRQ_DCDC5_V_LOW,
AXP15060_IRQ_DCDC6_V_LOW,
AXP15060_IRQ_PEK_LONG,
AXP15060_IRQ_PEK_SHORT,
AXP15060_IRQ_GPIO1_INPUT,
AXP15060_IRQ_PEK_FAL_EDGE,
AXP15060_IRQ_PEK_RIS_EDGE,
AXP15060_IRQ_GPIO2_INPUT,
};
struct axp20x_dev {
struct device *dev;
int irq;
......
......@@ -68,9 +68,6 @@ struct mfd_cell {
int id;
int level;
int (*enable)(struct platform_device *dev);
int (*disable)(struct platform_device *dev);
int (*suspend)(struct platform_device *dev);
int (*resume)(struct platform_device *dev);
......@@ -78,6 +75,9 @@ struct mfd_cell {
void *platform_data;
size_t pdata_size;
/* Matches ACPI */
const struct mfd_cell_acpi_match *acpi_match;
/* Software node for the device. */
const struct software_node *swnode;
......@@ -97,9 +97,6 @@ struct mfd_cell {
/* Set to 'true' to use 'of_reg' (above) - allows for of_reg=0 */
bool use_of_reg;
/* Matches ACPI */
const struct mfd_cell_acpi_match *acpi_match;
/*
* These resources can be specified relative to the parent device.
* For accessing hardware you should use resources from the platform dev
......@@ -119,19 +116,10 @@ struct mfd_cell {
/* A list of regulator supplies that should be mapped to the MFD
* device rather than the child device when requested
*/
const char * const *parent_supplies;
int num_parent_supplies;
const char * const *parent_supplies;
};
/*
* Convenience functions for clients using shared cells. Refcounting
* happens automatically, with the cell's enable/disable callbacks
* being called only when a device is first being enabled or no other
* clients are making use of it.
*/
extern int mfd_cell_enable(struct platform_device *pdev);
extern int mfd_cell_disable(struct platform_device *pdev);
/*
* Given a platform device that's been created by mfd_add_devices(), fetch
* the mfd_cell that created it.
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Device driver for regulators in MAX5970 and MAX5978 IC
*
* Copyright (c) 2022 9elements GmbH
*
* Author: Patrick Rudolph <patrick.rudolph@9elements.com>
*/
#ifndef _MFD_MAX597X_H
#define _MFD_MAX597X_H
#include <linux/regmap.h>
#define MAX5970_NUM_SWITCHES 2
#define MAX5978_NUM_SWITCHES 1
#define MAX597X_NUM_LEDS 4
struct max597x_data {
int num_switches;
u32 irng[MAX5970_NUM_SWITCHES];
u32 mon_rng[MAX5970_NUM_SWITCHES];
u32 shunt_micro_ohms[MAX5970_NUM_SWITCHES];
};
enum max597x_chip_type {
MAX597x_TYPE_MAX5978 = 1,
MAX597x_TYPE_MAX5970,
};
#define MAX5970_REG_CURRENT_L(ch) (0x01 + (ch) * 4)
#define MAX5970_REG_CURRENT_H(ch) (0x00 + (ch) * 4)
#define MAX5970_REG_VOLTAGE_L(ch) (0x03 + (ch) * 4)
#define MAX5970_REG_VOLTAGE_H(ch) (0x02 + (ch) * 4)
#define MAX5970_REG_MON_RANGE 0x18
#define MAX5970_MON_MASK 0x3
#define MAX5970_MON(reg, ch) (((reg) >> ((ch) * 2)) & MAX5970_MON_MASK)
#define MAX5970_MON_MAX_RANGE_UV 16000000
#define MAX5970_REG_CH_UV_WARN_H(ch) (0x1A + (ch) * 10)
#define MAX5970_REG_CH_UV_WARN_L(ch) (0x1B + (ch) * 10)
#define MAX5970_REG_CH_UV_CRIT_H(ch) (0x1C + (ch) * 10)
#define MAX5970_REG_CH_UV_CRIT_L(ch) (0x1D + (ch) * 10)
#define MAX5970_REG_CH_OV_WARN_H(ch) (0x1E + (ch) * 10)
#define MAX5970_REG_CH_OV_WARN_L(ch) (0x1F + (ch) * 10)
#define MAX5970_REG_CH_OV_CRIT_H(ch) (0x20 + (ch) * 10)
#define MAX5970_REG_CH_OV_CRIT_L(ch) (0x21 + (ch) * 10)
#define MAX5970_VAL2REG_H(x) (((x) >> 2) & 0xFF)
#define MAX5970_VAL2REG_L(x) ((x) & 0x3)
#define MAX5970_REG_DAC_FAST(ch) (0x2E + (ch))
#define MAX5970_FAST2SLOW_RATIO 200
#define MAX5970_REG_STATUS0 0x31
#define MAX5970_CB_IFAULTF(ch) (1 << (ch))
#define MAX5970_CB_IFAULTS(ch) (1 << ((ch) + 4))
#define MAX5970_REG_STATUS1 0x32
#define STATUS1_PROT_MASK 0x3
#define STATUS1_PROT(reg) \
(((reg) >> 6) & STATUS1_PROT_MASK)
#define STATUS1_PROT_SHUTDOWN 0
#define STATUS1_PROT_CLEAR_PG 1
#define STATUS1_PROT_ALERT_ONLY 2
#define MAX5970_REG_STATUS2 0x33
#define MAX5970_IRNG_MASK 0x3
#define MAX5970_IRNG(reg, ch) \
(((reg) >> ((ch) * 2)) & MAX5970_IRNG_MASK)
#define MAX5970_REG_STATUS3 0x34
#define MAX5970_STATUS3_ALERT BIT(4)
#define MAX5970_STATUS3_PG(ch) BIT(ch)
#define MAX5970_REG_FAULT0 0x35
#define UV_STATUS_WARN(ch) (1 << (ch))
#define UV_STATUS_CRIT(ch) (1 << ((ch) + 4))
#define MAX5970_REG_FAULT1 0x36
#define OV_STATUS_WARN(ch) (1 << (ch))
#define OV_STATUS_CRIT(ch) (1 << ((ch) + 4))
#define MAX5970_REG_FAULT2 0x37
#define OC_STATUS_WARN(ch) (1 << (ch))
#define MAX5970_REG_CHXEN 0x3b
#define CHXEN(ch) (3 << ((ch) * 2))
#define MAX5970_REG_LED_FLASH 0x43
#define MAX_REGISTERS 0x49
#define ADC_MASK 0x3FF
#endif /* _MFD_MAX597X_H */
......@@ -8,6 +8,9 @@
#ifndef __LINUX_MFD_RSMU_H
#define __LINUX_MFD_RSMU_H
#define RSMU_MAX_WRITE_COUNT (255)
#define RSMU_MAX_READ_COUNT (255)
/* The supported devices are ClockMatrix, Sabre and SnowLotus */
enum rsmu_type {
RSMU_CM = 0x34000,
......@@ -31,6 +34,6 @@ struct rsmu_ddata {
struct regmap *regmap;
struct mutex lock;
enum rsmu_type type;
u16 page;
u32 page;
};
#endif /* __LINUX_MFD_RSMU_H */
......@@ -107,14 +107,13 @@ enum rt5033_reg {
#define RT5033_LDO_CTRL_MASK 0x1f
/* RT5033 charger property - model, manufacturer */
#define RT5033_CHARGER_MODEL "RT5033WSC Charger"
#define RT5033_MANUFACTURER "Richtek Technology Corporation"
/*
* RT5033 charger fast-charge current lmits (as in CHGCTRL1 register),
* AICR mode limits the input current for example,
* the AIRC 100 mode limits the input current to 100 mA.
* While RT5033 charger can limit the fast-charge current (as in CHGCTRL1
* register), AICR mode limits the input current. For example, the AIRC 100
* mode limits the input current to 100 mA.
*/
#define RT5033_AICR_100_MODE 0x20
#define RT5033_AICR_500_MODE 0x40
......@@ -139,10 +138,9 @@ enum rt5033_reg {
#define RT5033_TE_ENABLE_MASK 0x08
/*
* RT5033 charger opa mode. RT50300 have two opa mode charger mode
* and boost mode for OTG
* RT5033 charger opa mode. RT5033 has two opa modes for OTG: charger mode
* and boost mode.
*/
#define RT5033_CHARGER_MODE 0x00
#define RT5033_BOOST_MODE 0x01
......@@ -181,18 +179,17 @@ enum rt5033_reg {
* RT5033 charger pre-charge threshold volt limits
* (as in CHGCTRL5 register), uV
*/
#define RT5033_CHARGER_PRE_THRESHOLD_LIMIT_MIN 2300000U
#define RT5033_CHARGER_PRE_THRESHOLD_STEP_NUM 100000U
#define RT5033_CHARGER_PRE_THRESHOLD_LIMIT_MAX 3800000U
/*
* RT5033 charger enable UUG, If UUG enable MOS auto control by H/W charger
* RT5033 charger UUG. It enables MOS auto control by H/W charger
* circuit.
*/
#define RT5033_CHARGER_UUG_ENABLE 0x02
/* RT5033 charger High impedance mode */
/* RT5033 charger high impedance mode */
#define RT5033_CHARGER_HZ_DISABLE 0x00
#define RT5033_CHARGER_HZ_ENABLE 0x01
......
......@@ -49,10 +49,9 @@ struct rt5033_charger_data {
};
struct rt5033_charger {
struct device *dev;
struct rt5033_dev *rt5033;
struct power_supply psy;
struct device *dev;
struct rt5033_dev *rt5033;
struct power_supply psy;
struct rt5033_charger_data *chg;
};
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2022 Renesas Electronics Corporation
*/
#ifndef __MFD_RZ_MTU3_H__
#define __MFD_RZ_MTU3_H__
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/mutex.h>
/* 8-bit shared register offsets macros */
#define RZ_MTU3_TSTRA 0x080 /* Timer start register A */
#define RZ_MTU3_TSTRB 0x880 /* Timer start register B */
/* 16-bit shared register offset macros */
#define RZ_MTU3_TDDRA 0x016 /* Timer dead time data register A */
#define RZ_MTU3_TDDRB 0x816 /* Timer dead time data register B */
#define RZ_MTU3_TCDRA 0x014 /* Timer cycle data register A */
#define RZ_MTU3_TCDRB 0x814 /* Timer cycle data register B */
#define RZ_MTU3_TCBRA 0x022 /* Timer cycle buffer register A */
#define RZ_MTU3_TCBRB 0x822 /* Timer cycle buffer register B */
#define RZ_MTU3_TCNTSA 0x020 /* Timer subcounter A */
#define RZ_MTU3_TCNTSB 0x820 /* Timer subcounter B */
/*
* MTU5 contains 3 timer counter registers and is totaly different
* from other channels, so we must separate its offset
*/
/* 8-bit register offset macros of MTU3 channels except MTU5 */
#define RZ_MTU3_TIER 0 /* Timer interrupt register */
#define RZ_MTU3_NFCR 1 /* Noise filter control register */
#define RZ_MTU3_TSR 2 /* Timer status register */
#define RZ_MTU3_TCR 3 /* Timer control register */
#define RZ_MTU3_TCR2 4 /* Timer control register 2 */
/* Timer mode register 1 */
#define RZ_MTU3_TMDR1 5
#define RZ_MTU3_TMDR1_MD GENMASK(3, 0)
#define RZ_MTU3_TMDR1_MD_NORMAL FIELD_PREP(RZ_MTU3_TMDR1_MD, 0)
#define RZ_MTU3_TMDR1_MD_PWMMODE1 FIELD_PREP(RZ_MTU3_TMDR1_MD, 2)
#define RZ_MTU3_TIOR 6 /* Timer I/O control register */
#define RZ_MTU3_TIORH 6 /* Timer I/O control register H */
#define RZ_MTU3_TIORL 7 /* Timer I/O control register L */
/* Only MTU3/4/6/7 have TBTM registers */
#define RZ_MTU3_TBTM 8 /* Timer buffer operation transfer mode register */
/* 8-bit MTU5 register offset macros */
#define RZ_MTU3_TSTR 2 /* MTU5 Timer start register */
#define RZ_MTU3_TCNTCMPCLR 3 /* MTU5 Timer compare match clear register */
#define RZ_MTU3_TCRU 4 /* Timer control register U */
#define RZ_MTU3_TCR2U 5 /* Timer control register 2U */
#define RZ_MTU3_TIORU 6 /* Timer I/O control register U */
#define RZ_MTU3_TCRV 7 /* Timer control register V */
#define RZ_MTU3_TCR2V 8 /* Timer control register 2V */
#define RZ_MTU3_TIORV 9 /* Timer I/O control register V */
#define RZ_MTU3_TCRW 10 /* Timer control register W */
#define RZ_MTU3_TCR2W 11 /* Timer control register 2W */
#define RZ_MTU3_TIORW 12 /* Timer I/O control register W */
/* 16-bit register offset macros of MTU3 channels except MTU5 */
#define RZ_MTU3_TCNT 0 /* Timer counter */
#define RZ_MTU3_TGRA 1 /* Timer general register A */
#define RZ_MTU3_TGRB 2 /* Timer general register B */
#define RZ_MTU3_TGRC 3 /* Timer general register C */
#define RZ_MTU3_TGRD 4 /* Timer general register D */
#define RZ_MTU3_TGRE 5 /* Timer general register E */
#define RZ_MTU3_TGRF 6 /* Timer general register F */
/* Timer A/D converter start request registers */
#define RZ_MTU3_TADCR 7 /* control register */
#define RZ_MTU3_TADCORA 8 /* cycle set register A */
#define RZ_MTU3_TADCORB 9 /* cycle set register B */
#define RZ_MTU3_TADCOBRA 10 /* cycle set buffer register A */
#define RZ_MTU3_TADCOBRB 11 /* cycle set buffer register B */
/* 16-bit MTU5 register offset macros */
#define RZ_MTU3_TCNTU 0 /* MTU5 Timer counter U */
#define RZ_MTU3_TGRU 1 /* MTU5 Timer general register U */
#define RZ_MTU3_TCNTV 2 /* MTU5 Timer counter V */
#define RZ_MTU3_TGRV 3 /* MTU5 Timer general register V */
#define RZ_MTU3_TCNTW 4 /* MTU5 Timer counter W */
#define RZ_MTU3_TGRW 5 /* MTU5 Timer general register W */
/* 32-bit register offset */
#define RZ_MTU3_TCNTLW 0 /* Timer longword counter */
#define RZ_MTU3_TGRALW 1 /* Timer longword general register A */
#define RZ_MTU3_TGRBLW 2 /* Timer longowrd general register B */
#define RZ_MTU3_TMDR3 0x191 /* MTU1 Timer Mode Register 3 */
/* Macros for setting registers */
#define RZ_MTU3_TCR_CCLR GENMASK(7, 5)
#define RZ_MTU3_TCR_CKEG GENMASK(4, 3)
#define RZ_MTU3_TCR_TPCS GENMASK(2, 0)
#define RZ_MTU3_TCR_CCLR_TGRA BIT(5)
#define RZ_MTU3_TCR_CCLR_TGRC FIELD_PREP(RZ_MTU3_TCR_CCLR, 5)
#define RZ_MTU3_TCR_CKEG_RISING FIELD_PREP(RZ_MTU3_TCR_CKEG, 0)
#define RZ_MTU3_TIOR_IOB GENMASK(7, 4)
#define RZ_MTU3_TIOR_IOA GENMASK(3, 0)
#define RZ_MTU3_TIOR_OC_RETAIN 0
#define RZ_MTU3_TIOR_OC_INIT_OUT_LO_HI_OUT 2
#define RZ_MTU3_TIOR_OC_INIT_OUT_HI_TOGGLE_OUT 7
#define RZ_MTU3_TIOR_OC_IOA_H_COMP_MATCH \
FIELD_PREP(RZ_MTU3_TIOR_IOA, RZ_MTU3_TIOR_OC_INIT_OUT_LO_HI_OUT)
#define RZ_MTU3_TIOR_OC_IOB_TOGGLE \
FIELD_PREP(RZ_MTU3_TIOR_IOB, RZ_MTU3_TIOR_OC_INIT_OUT_HI_TOGGLE_OUT)
enum rz_mtu3_channels {
RZ_MTU3_CHAN_0,
RZ_MTU3_CHAN_1,
RZ_MTU3_CHAN_2,
RZ_MTU3_CHAN_3,
RZ_MTU3_CHAN_4,
RZ_MTU3_CHAN_5,
RZ_MTU3_CHAN_6,
RZ_MTU3_CHAN_7,
RZ_MTU3_CHAN_8,
RZ_MTU_NUM_CHANNELS
};
/**
* struct rz_mtu3_channel - MTU3 channel private data
*
* @dev: device handle
* @channel_number: channel number
* @lock: Lock to protect channel state
* @is_busy: channel state
*/
struct rz_mtu3_channel {
struct device *dev;
unsigned int channel_number;
struct mutex lock;
bool is_busy;
};
/**
* struct rz_mtu3 - MTU3 core private data
*
* @clk: MTU3 module clock
* @rz_mtu3_channel: HW channels
* @priv_data: MTU3 core driver private data
*/
struct rz_mtu3 {
struct clk *clk;
struct rz_mtu3_channel channels[RZ_MTU_NUM_CHANNELS];
void *priv_data;
};
#if IS_ENABLED(CONFIG_RZ_MTU3)
static inline bool rz_mtu3_request_channel(struct rz_mtu3_channel *ch)
{
mutex_lock(&ch->lock);
if (ch->is_busy) {
mutex_unlock(&ch->lock);
return false;
}
ch->is_busy = true;
mutex_unlock(&ch->lock);
return true;
}
static inline void rz_mtu3_release_channel(struct rz_mtu3_channel *ch)
{
mutex_lock(&ch->lock);
ch->is_busy = false;
mutex_unlock(&ch->lock);
}
bool rz_mtu3_is_enabled(struct rz_mtu3_channel *ch);
void rz_mtu3_disable(struct rz_mtu3_channel *ch);
int rz_mtu3_enable(struct rz_mtu3_channel *ch);
u8 rz_mtu3_8bit_ch_read(struct rz_mtu3_channel *ch, u16 off);
u16 rz_mtu3_16bit_ch_read(struct rz_mtu3_channel *ch, u16 off);
u32 rz_mtu3_32bit_ch_read(struct rz_mtu3_channel *ch, u16 off);
u16 rz_mtu3_shared_reg_read(struct rz_mtu3_channel *ch, u16 off);
void rz_mtu3_8bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u8 val);
void rz_mtu3_16bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u16 val);
void rz_mtu3_32bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u32 val);
void rz_mtu3_shared_reg_write(struct rz_mtu3_channel *ch, u16 off, u16 val);
void rz_mtu3_shared_reg_update_bit(struct rz_mtu3_channel *ch, u16 off,
u16 pos, u8 val);
#else
static inline bool rz_mtu3_request_channel(struct rz_mtu3_channel *ch)
{
return false;
}
static inline void rz_mtu3_release_channel(struct rz_mtu3_channel *ch)
{
}
static inline bool rz_mtu3_is_enabled(struct rz_mtu3_channel *ch)
{
return false;
}
static inline void rz_mtu3_disable(struct rz_mtu3_channel *ch)
{
}
static inline int rz_mtu3_enable(struct rz_mtu3_channel *ch)
{
return 0;
}
static inline u8 rz_mtu3_8bit_ch_read(struct rz_mtu3_channel *ch, u16 off)
{
return 0;
}
static inline u16 rz_mtu3_16bit_ch_read(struct rz_mtu3_channel *ch, u16 off)
{
return 0;
}
static inline u32 rz_mtu3_32bit_ch_read(struct rz_mtu3_channel *ch, u16 off)
{
return 0;
}
static inline u16 rz_mtu3_shared_reg_read(struct rz_mtu3_channel *ch, u16 off)
{
return 0;
}
static inline void rz_mtu3_8bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u8 val)
{
}
static inline void rz_mtu3_16bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u16 val)
{
}
static inline void rz_mtu3_32bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u32 val)
{
}
static inline void rz_mtu3_shared_reg_write(struct rz_mtu3_channel *ch, u16 off, u16 val)
{
}
static inline void rz_mtu3_shared_reg_update_bit(struct rz_mtu3_channel *ch,
u16 off, u16 pos, u8 val)
{
}
#endif
#endif /* __MFD_RZ_MTU3_H__ */
......@@ -36,8 +36,6 @@
struct gpio_desc;
enum sec_device_type {
S5M8751X,
S5M8763X,
S5M8767X,
S2MPA01,
S2MPS11X,
......
......@@ -194,54 +194,4 @@ enum s5m8767_irq {
#define S5M8767_IRQ_RTC1S_MASK (1 << 4)
#define S5M8767_IRQ_WTSR_MASK (1 << 5)
enum s5m8763_irq {
S5M8763_IRQ_DCINF,
S5M8763_IRQ_DCINR,
S5M8763_IRQ_JIGF,
S5M8763_IRQ_JIGR,
S5M8763_IRQ_PWRONF,
S5M8763_IRQ_PWRONR,
S5M8763_IRQ_WTSREVNT,
S5M8763_IRQ_SMPLEVNT,
S5M8763_IRQ_ALARM1,
S5M8763_IRQ_ALARM0,
S5M8763_IRQ_ONKEY1S,
S5M8763_IRQ_TOPOFFR,
S5M8763_IRQ_DCINOVPR,
S5M8763_IRQ_CHGRSTF,
S5M8763_IRQ_DONER,
S5M8763_IRQ_CHGFAULT,
S5M8763_IRQ_LOBAT1,
S5M8763_IRQ_LOBAT2,
S5M8763_IRQ_NR,
};
#define S5M8763_IRQ_DCINF_MASK (1 << 2)
#define S5M8763_IRQ_DCINR_MASK (1 << 3)
#define S5M8763_IRQ_JIGF_MASK (1 << 4)
#define S5M8763_IRQ_JIGR_MASK (1 << 5)
#define S5M8763_IRQ_PWRONF_MASK (1 << 6)
#define S5M8763_IRQ_PWRONR_MASK (1 << 7)
#define S5M8763_IRQ_WTSREVNT_MASK (1 << 0)
#define S5M8763_IRQ_SMPLEVNT_MASK (1 << 1)
#define S5M8763_IRQ_ALARM1_MASK (1 << 2)
#define S5M8763_IRQ_ALARM0_MASK (1 << 3)
#define S5M8763_IRQ_ONKEY1S_MASK (1 << 0)
#define S5M8763_IRQ_TOPOFFR_MASK (1 << 2)
#define S5M8763_IRQ_DCINOVPR_MASK (1 << 3)
#define S5M8763_IRQ_CHGRSTF_MASK (1 << 4)
#define S5M8763_IRQ_DONER_MASK (1 << 5)
#define S5M8763_IRQ_CHGFAULT_MASK (1 << 7)
#define S5M8763_IRQ_LOBAT1_MASK (1 << 0)
#define S5M8763_IRQ_LOBAT2_MASK (1 << 1)
#define S5M8763_ENRAMP (1 << 4)
#endif /* __LINUX_MFD_SEC_IRQ_H */
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) 2011 Samsung Electronics Co., Ltd
* http://www.samsung.com
*/
#ifndef __LINUX_MFD_S5M8763_H
#define __LINUX_MFD_S5M8763_H
/* S5M8763 registers */
enum s5m8763_reg {
S5M8763_REG_IRQ1,
S5M8763_REG_IRQ2,
S5M8763_REG_IRQ3,
S5M8763_REG_IRQ4,
S5M8763_REG_IRQM1,
S5M8763_REG_IRQM2,
S5M8763_REG_IRQM3,
S5M8763_REG_IRQM4,
S5M8763_REG_STATUS1,
S5M8763_REG_STATUS2,
S5M8763_REG_STATUSM1,
S5M8763_REG_STATUSM2,
S5M8763_REG_CHGR1,
S5M8763_REG_CHGR2,
S5M8763_REG_LDO_ACTIVE_DISCHARGE1,
S5M8763_REG_LDO_ACTIVE_DISCHARGE2,
S5M8763_REG_BUCK_ACTIVE_DISCHARGE3,
S5M8763_REG_ONOFF1,
S5M8763_REG_ONOFF2,
S5M8763_REG_ONOFF3,
S5M8763_REG_ONOFF4,
S5M8763_REG_BUCK1_VOLTAGE1,
S5M8763_REG_BUCK1_VOLTAGE2,
S5M8763_REG_BUCK1_VOLTAGE3,
S5M8763_REG_BUCK1_VOLTAGE4,
S5M8763_REG_BUCK2_VOLTAGE1,
S5M8763_REG_BUCK2_VOLTAGE2,
S5M8763_REG_BUCK3,
S5M8763_REG_BUCK4,
S5M8763_REG_LDO1_LDO2,
S5M8763_REG_LDO3,
S5M8763_REG_LDO4,
S5M8763_REG_LDO5,
S5M8763_REG_LDO6,
S5M8763_REG_LDO7,
S5M8763_REG_LDO7_LDO8,
S5M8763_REG_LDO9_LDO10,
S5M8763_REG_LDO11,
S5M8763_REG_LDO12,
S5M8763_REG_LDO13,
S5M8763_REG_LDO14,
S5M8763_REG_LDO15,
S5M8763_REG_LDO16,
S5M8763_REG_BKCHR,
S5M8763_REG_LBCNFG1,
S5M8763_REG_LBCNFG2,
};
/* S5M8763 regulator ids */
enum s5m8763_regulators {
S5M8763_LDO1,
S5M8763_LDO2,
S5M8763_LDO3,
S5M8763_LDO4,
S5M8763_LDO5,
S5M8763_LDO6,
S5M8763_LDO7,
S5M8763_LDO8,
S5M8763_LDO9,
S5M8763_LDO10,
S5M8763_LDO11,
S5M8763_LDO12,
S5M8763_LDO13,
S5M8763_LDO14,
S5M8763_LDO15,
S5M8763_LDO16,
S5M8763_BUCK1,
S5M8763_BUCK2,
S5M8763_BUCK3,
S5M8763_BUCK4,
S5M8763_AP_EN32KHZ,
S5M8763_CP_EN32KHZ,
S5M8763_ENCHGVI,
S5M8763_ESAFEUSB1,
S5M8763_ESAFEUSB2,
};
#define S5M8763_ENRAMP (1 << 4)
#endif /* __LINUX_MFD_S5M8763_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment