Merge 2d7b4cdbb5 ("Merge tag 'backlight-next-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight") into android-mainline
Steps on the way to 5.15-rc1 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I6395e9878d60dbb4c0faf23b49ad05f697f80b72
This commit is contained in:
@@ -26,10 +26,10 @@ Required properties:
|
||||
* "x-powers,axp803"
|
||||
* "x-powers,axp806"
|
||||
* "x-powers,axp805", "x-powers,axp806"
|
||||
* "x-powers,axp305", "x-powers,axp805", "x-powers,axp806"
|
||||
* "x-powers,axp809"
|
||||
* "x-powers,axp813"
|
||||
- reg: The I2C slave address or RSB hardware address for the AXP chip
|
||||
- interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
|
||||
- interrupt-controller: The PMIC has its own internal IRQs
|
||||
- #interrupt-cells: Should be set to 1
|
||||
|
||||
@@ -43,6 +43,7 @@ more information:
|
||||
AXP20x/LDO3: software-based implementation
|
||||
|
||||
Optional properties:
|
||||
- interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
|
||||
- x-powers,dcdc-freq: defines the work frequency of DC-DC in KHz
|
||||
AXP152/20X: range: 750-1875, Default: 1.5 MHz
|
||||
AXP22X/8XX: range: 1800-4050, Default: 3 MHz
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mfd/brcm,cru.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom CRU
|
||||
|
||||
maintainers:
|
||||
- Rafał Miłecki <rafal@milecki.pl>
|
||||
|
||||
description: |
|
||||
Broadcom CRU ("Clock and Reset Unit" or "Central Resource Unit") is a hardware
|
||||
block grouping smaller blocks. On Broadcom Northstar platform it contains e.g.
|
||||
clocks, pinctrl, USB PHY and thermal.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- brcm,ns-cru
|
||||
- const: simple-mfd
|
||||
|
||||
reg:
|
||||
description: CRU registers
|
||||
|
||||
ranges: true
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 1
|
||||
|
||||
pinctrl:
|
||||
$ref: ../pinctrl/brcm,ns-pinmux.yaml
|
||||
|
||||
patternProperties:
|
||||
'^clock-controller@[a-f0-9]+$':
|
||||
$ref: ../clock/brcm,iproc-clocks.yaml
|
||||
|
||||
'^thermal@[a-f0-9]+$':
|
||||
$ref: ../thermal/brcm,ns-thermal.yaml
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
examples:
|
||||
- |
|
||||
cru-bus@1800c100 {
|
||||
compatible = "brcm,ns-cru", "simple-mfd";
|
||||
reg = <0x1800c100 0x1d0>;
|
||||
ranges;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
clock-controller@100 {
|
||||
#clock-cells = <1>;
|
||||
compatible = "brcm,nsp-lcpll0";
|
||||
reg = <0x100 0x14>;
|
||||
clocks = <&osc>;
|
||||
clock-output-names = "lcpll0", "pcie_phy", "sdio", "ddr_phy";
|
||||
};
|
||||
|
||||
clock-controller@140 {
|
||||
#clock-cells = <1>;
|
||||
compatible = "brcm,nsp-genpll";
|
||||
reg = <0x140 0x24>;
|
||||
clocks = <&osc>;
|
||||
clock-output-names = "genpll", "phy", "ethernetclk", "usbclk",
|
||||
"iprocfast", "sata1", "sata2";
|
||||
};
|
||||
|
||||
pinctrl {
|
||||
compatible = "brcm,bcm4708-pinmux";
|
||||
offset = <0x1c0>;
|
||||
};
|
||||
|
||||
thermal@2c0 {
|
||||
compatible = "brcm,ns-thermal";
|
||||
reg = <0x2c0 0x10>;
|
||||
#thermal-sensor-cells = <0>;
|
||||
};
|
||||
};
|
||||
@@ -53,7 +53,9 @@ patternProperties:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,pm8008-gpio
|
||||
items:
|
||||
- const: qcom,pm8008-gpio
|
||||
- const: qcom,spmi-gpio
|
||||
|
||||
reg:
|
||||
description: Peripheral address of one of the two GPIO peripherals.
|
||||
@@ -61,6 +63,9 @@ patternProperties:
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
gpio-ranges:
|
||||
maxItems: 1
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
"#interrupt-cells":
|
||||
@@ -75,6 +80,7 @@ patternProperties:
|
||||
- gpio-controller
|
||||
- interrupt-controller
|
||||
- "#gpio-cells"
|
||||
- gpio-ranges
|
||||
- "#interrupt-cells"
|
||||
|
||||
additionalProperties: false
|
||||
@@ -107,10 +113,11 @@ examples:
|
||||
interrupt-parent = <&tlmm>;
|
||||
interrupts = <32 IRQ_TYPE_EDGE_RISING>;
|
||||
|
||||
gpio@c000 {
|
||||
compatible = "qcom,pm8008-gpio";
|
||||
pm8008_gpios: gpio@c000 {
|
||||
compatible = "qcom,pm8008-gpio", "qcom,spmi-gpio";
|
||||
reg = <0xc000>;
|
||||
gpio-controller;
|
||||
gpio-ranges = <&pm8008_gpios 0 0 2>;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
|
||||
@@ -45,9 +45,12 @@ properties:
|
||||
- microchip,sparx5-cpu-syscon
|
||||
- mstar,msc313-pmsleep
|
||||
- rockchip,px30-qos
|
||||
- rockchip,rk3036-qos
|
||||
- rockchip,rk3066-qos
|
||||
- rockchip,rk3228-qos
|
||||
- rockchip,rk3288-qos
|
||||
- rockchip,rk3399-qos
|
||||
- rockchip,rk3568-qos
|
||||
- samsung,exynos3-sysreg
|
||||
- samsung,exynos4-sysreg
|
||||
- samsung,exynos5-sysreg
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mfd/ti,tps65086.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: TPS65086 Power Management Integrated Circuit (PMIC)
|
||||
|
||||
maintainers:
|
||||
- Emil Renner Berthing <kernel@esmil.dk>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ti,tps65086
|
||||
|
||||
reg:
|
||||
const: 0x5e
|
||||
description: I2C slave address
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
'#interrupt-cells':
|
||||
const: 2
|
||||
description: |
|
||||
The first cell is the IRQ number. The second cell is the flags,
|
||||
encoded as trigger masks from ../interrupt-controller/interrupts.txt.
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
'#gpio-cells':
|
||||
const: 2
|
||||
description: |
|
||||
The first cell is the pin number and the second cell is used to specify
|
||||
flags. See ../gpio/gpio.txt for more information.
|
||||
|
||||
regulators:
|
||||
type: object
|
||||
description: |
|
||||
List of child nodes that specify the regulator initialization data.
|
||||
Child nodes must be named after their hardware counterparts:
|
||||
buck[1-6], ldoa[1-3], swa1, swb[1-2], and vtt.
|
||||
Each child node is defined using the standard binding for regulators and
|
||||
the optional regulator properties defined below.
|
||||
|
||||
patternProperties:
|
||||
"^buck[1-6]$":
|
||||
type: object
|
||||
$ref: ../regulator/regulator.yaml
|
||||
|
||||
properties:
|
||||
regulator-name: true
|
||||
regulator-boot-on: true
|
||||
regulator-always-on: true
|
||||
regulator-min-microvolt: true
|
||||
regulator-max-microvolt: true
|
||||
ti,regulator-step-size-25mv:
|
||||
type: boolean
|
||||
description: |
|
||||
Set this if the regulator is factory set with a 25mv step voltage
|
||||
mapping.
|
||||
ti,regulator-decay:
|
||||
type: boolean
|
||||
description: |
|
||||
Set this if the output needs to decay, default is for the output
|
||||
to slew down.
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
"^(ldoa[1-3]|swa1|swb[1-2]|vtt)$":
|
||||
type: object
|
||||
$ref: ../regulator/regulator.yaml
|
||||
|
||||
properties:
|
||||
regulator-name: true
|
||||
regulator-boot-on: true
|
||||
regulator-always-on: true
|
||||
regulator-min-microvolt: true
|
||||
regulator-max-microvolt: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- gpio-controller
|
||||
- '#gpio-cells'
|
||||
- regulators
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2c0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pmic: pmic@5e {
|
||||
compatible = "ti,tps65086";
|
||||
reg = <0x5e>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <28 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
regulators {
|
||||
buck1 {
|
||||
regulator-name = "vcc1";
|
||||
regulator-min-microvolt = <1600000>;
|
||||
regulator-max-microvolt = <1600000>;
|
||||
regulator-boot-on;
|
||||
ti,regulator-decay;
|
||||
ti,regulator-step-size-25mv;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
@@ -1,54 +0,0 @@
|
||||
* TPS65086 Power Management Integrated Circuit (PMIC) bindings
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "ti,tps65086".
|
||||
- reg : I2C slave address.
|
||||
- interrupts : The interrupt line the device is connected to.
|
||||
- interrupt-controller : Marks the device node as an interrupt controller.
|
||||
- #interrupt-cells : The number of cells to describe an IRQ, should be 2.
|
||||
The first cell is the IRQ number.
|
||||
The second cell is the flags, encoded as trigger
|
||||
masks from ../interrupt-controller/interrupts.txt.
|
||||
- gpio-controller : Marks the device node as a GPIO Controller.
|
||||
- #gpio-cells : Should be two. The first cell is the pin number and
|
||||
the second cell is used to specify flags.
|
||||
See ../gpio/gpio.txt for more information.
|
||||
- regulators: : List of child nodes that specify the regulator
|
||||
initialization data. Child nodes must be named
|
||||
after their hardware counterparts: buck[1-6],
|
||||
ldoa[1-3], swa1, swb[1-2], and vtt. Each child
|
||||
node is defined using the standard binding for
|
||||
regulators and the optional regulator properties
|
||||
defined below.
|
||||
|
||||
Optional regulator properties:
|
||||
- ti,regulator-step-size-25mv : This is applicable for buck[1-6], set this
|
||||
if the regulator is factory set with a 25mv
|
||||
step voltage mapping.
|
||||
- ti,regulator-decay : This is applicable for buck[1-6], set this if
|
||||
the output needs to decay, default is for
|
||||
the output to slew down.
|
||||
|
||||
Example:
|
||||
|
||||
pmic: tps65086@5e {
|
||||
compatible = "ti,tps65086";
|
||||
reg = <0x5e>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <28 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
regulators {
|
||||
buck1 {
|
||||
regulator-name = "vcc1";
|
||||
regulator-min-microvolt = <1600000>;
|
||||
regulator-max-microvolt = <1600000>;
|
||||
regulator-boot-on;
|
||||
ti,regulator-decay;
|
||||
ti,regulator-step-size-25mv;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -72,6 +72,10 @@ for the GPIO. Values can be:
|
||||
* GPIOD_OUT_HIGH_OPEN_DRAIN same as GPIOD_OUT_HIGH but also enforce the line
|
||||
to be electrically used with open drain.
|
||||
|
||||
Note that the initial value is *logical* and the physical line level depends on
|
||||
whether the line is configured active high or active low (see
|
||||
:ref:`active_low_semantics`).
|
||||
|
||||
The two last flags are used for use cases where open drain is mandatory, such
|
||||
as I2C: if the line is not already configured as open drain in the mappings
|
||||
(see board.txt), then open drain will be enforced anyway and a warning will be
|
||||
@@ -252,6 +256,8 @@ that can't be accessed from hardIRQ handlers, these calls act the same as the
|
||||
spinlock-safe calls.
|
||||
|
||||
|
||||
.. _active_low_semantics:
|
||||
|
||||
The active low and open drain semantics
|
||||
---------------------------------------
|
||||
As a consumer should not have to care about the physical line level, all of the
|
||||
@@ -309,9 +315,11 @@ work on the raw line value::
|
||||
void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value)
|
||||
int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
|
||||
|
||||
The active low state of a GPIO can also be queried using the following call::
|
||||
The active low state of a GPIO can also be queried and toggled using the
|
||||
following calls::
|
||||
|
||||
int gpiod_is_active_low(const struct gpio_desc *desc)
|
||||
void gpiod_toggle_active_low(struct gpio_desc *desc)
|
||||
|
||||
Note that these functions should only be used with great moderation; a driver
|
||||
should not have to care about the physical line level or open drain semantics.
|
||||
|
||||
@@ -547,13 +547,10 @@ To use the helpers please keep the following in mind:
|
||||
the irqchip can initialize. E.g. .dev and .can_sleep shall be set up
|
||||
properly.
|
||||
|
||||
- Nominally set all handlers to handle_bad_irq() in the setup call and pass
|
||||
handle_bad_irq() as flow handler parameter in gpiochip_irqchip_add() if it is
|
||||
expected for GPIO driver that irqchip .set_type() callback will be called
|
||||
before using/enabling each GPIO IRQ. Then set the handler to
|
||||
handle_level_irq() and/or handle_edge_irq() in the irqchip .set_type()
|
||||
callback depending on what your controller supports and what is requested
|
||||
by the consumer.
|
||||
- Nominally set gpio_irq_chip.handler to handle_bad_irq. Then, if your irqchip
|
||||
is cascaded, set the handler to handle_level_irq() and/or handle_edge_irq()
|
||||
in the irqchip .set_type() callback depending on what your controller
|
||||
supports and what is requested by the consumer.
|
||||
|
||||
|
||||
Locking IRQ usage
|
||||
|
||||
+10
-2
@@ -2271,7 +2271,6 @@ F: drivers/iio/adc/ab8500-gpadc.c
|
||||
F: drivers/mfd/ab8500*
|
||||
F: drivers/mfd/abx500*
|
||||
F: drivers/mfd/db8500*
|
||||
F: drivers/mfd/dbx500*
|
||||
F: drivers/pinctrl/nomadik/
|
||||
F: drivers/rtc/rtc-ab8500.c
|
||||
F: drivers/rtc/rtc-pl031.c
|
||||
@@ -19865,6 +19864,15 @@ F: Documentation/filesystems/virtiofs.rst
|
||||
F: fs/fuse/virtio_fs.c
|
||||
F: include/uapi/linux/virtio_fs.h
|
||||
|
||||
VIRTIO GPIO DRIVER
|
||||
M: Enrico Weigelt, metux IT consult <info@metux.net>
|
||||
M: Viresh Kumar <vireshk@kernel.org>
|
||||
L: linux-gpio@vger.kernel.org
|
||||
L: virtualization@lists.linux-foundation.org
|
||||
S: Maintained
|
||||
F: drivers/gpio/gpio-virtio.c
|
||||
F: include/uapi/linux/virtio_gpio.h
|
||||
|
||||
VIRTIO GPU DRIVER
|
||||
M: David Airlie <airlied@linux.ie>
|
||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||
@@ -20559,7 +20567,7 @@ R: Srinivas Neeli <srinivas.neeli@xilinx.com>
|
||||
R: Michal Simek <michal.simek@xilinx.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/gpio/gpio-xilinx.txt
|
||||
F: Documentation/devicetree/bindings/gpio/gpio-zynq.txt
|
||||
F: Documentation/devicetree/bindings/gpio/gpio-zynq.yaml
|
||||
F: drivers/gpio/gpio-xilinx.c
|
||||
F: drivers/gpio/gpio-zynq.c
|
||||
|
||||
|
||||
@@ -99,10 +99,11 @@ static void u8500_clk_init(struct device_node *np)
|
||||
if (fw_version != NULL) {
|
||||
switch (fw_version->project) {
|
||||
case PRCMU_FW_PROJECT_U8500_C2:
|
||||
case PRCMU_FW_PROJECT_U8500_MBL:
|
||||
case PRCMU_FW_PROJECT_U8500_SSG1:
|
||||
case PRCMU_FW_PROJECT_U8520:
|
||||
case PRCMU_FW_PROJECT_U8420:
|
||||
case PRCMU_FW_PROJECT_U8420_SYSCLK:
|
||||
case PRCMU_FW_PROJECT_U8500_SSG2:
|
||||
sgaclk_parent = "soc0_pll";
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -117,7 +117,7 @@ static int dbx500_cpuidle_probe(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver dbx500_cpuidle_plat_driver = {
|
||||
.driver = {
|
||||
.name = "cpuidle-dbx500",
|
||||
.name = "db8500-cpuidle",
|
||||
},
|
||||
.probe = dbx500_cpuidle_probe,
|
||||
};
|
||||
|
||||
@@ -1018,12 +1018,6 @@ config GPIO_MAX732X_IRQ
|
||||
Say yes here to enable the max732x to be used as an interrupt
|
||||
controller. It requires the driver to be built in the kernel.
|
||||
|
||||
config GPIO_MC9S08DZ60
|
||||
bool "MX35 3DS BOARD MC9S08DZ60 GPIO functions"
|
||||
depends on I2C=y && MACH_MX35_3DS
|
||||
help
|
||||
Select this to enable the MC9S08DZ60 GPIO driver
|
||||
|
||||
config GPIO_PCA953X
|
||||
tristate "PCA95[357]x, PCA9698, TCA64xx, and MAX7310 I/O ports"
|
||||
select REGMAP_I2C
|
||||
@@ -1677,6 +1671,15 @@ config GPIO_MOCKUP
|
||||
tools/testing/selftests/gpio/gpio-mockup.sh. Reference the usage in
|
||||
it.
|
||||
|
||||
config GPIO_VIRTIO
|
||||
tristate "VirtIO GPIO support"
|
||||
depends on VIRTIO
|
||||
help
|
||||
Say Y here to enable guest support for virtio-based GPIO controllers.
|
||||
|
||||
These virtual GPIOs can be routed to real GPIOs or attached to
|
||||
simulators on the host (like QEMU).
|
||||
|
||||
endmenu
|
||||
|
||||
endif
|
||||
|
||||
@@ -92,7 +92,6 @@ obj-$(CONFIG_GPIO_MAX77620) += gpio-max77620.o
|
||||
obj-$(CONFIG_GPIO_MAX77650) += gpio-max77650.o
|
||||
obj-$(CONFIG_GPIO_MB86S7X) += gpio-mb86s7x.o
|
||||
obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o
|
||||
obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o
|
||||
obj-$(CONFIG_GPIO_MENZ127) += gpio-menz127.o
|
||||
obj-$(CONFIG_GPIO_MERRIFIELD) += gpio-merrifield.o
|
||||
obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o
|
||||
@@ -166,6 +165,7 @@ obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o
|
||||
obj-$(CONFIG_GPIO_UNIPHIER) += gpio-uniphier.o
|
||||
obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o
|
||||
obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o
|
||||
obj-$(CONFIG_GPIO_VIRTIO) += gpio-virtio.o
|
||||
obj-$(CONFIG_GPIO_VISCONTI) += gpio-visconti.o
|
||||
obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o
|
||||
obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
|
||||
|
||||
@@ -17,37 +17,30 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
/*
|
||||
* MAX_NR_HW_GPIO represents the number of actual hardware-supported GPIOs (ie,
|
||||
* slots within the clocked serial GPIO data). Since each HW GPIO is both an
|
||||
* input and an output, we provide MAX_NR_HW_GPIO * 2 lines on our gpiochip
|
||||
* device.
|
||||
*
|
||||
* We use SGPIO_OUTPUT_OFFSET to define the split between the inputs and
|
||||
* outputs; the inputs start at line 0, the outputs start at OUTPUT_OFFSET.
|
||||
*/
|
||||
#define MAX_NR_HW_SGPIO 80
|
||||
#define SGPIO_OUTPUT_OFFSET MAX_NR_HW_SGPIO
|
||||
|
||||
#define ASPEED_SGPIO_CTRL 0x54
|
||||
|
||||
#define ASPEED_SGPIO_PINS_MASK GENMASK(9, 6)
|
||||
#define ASPEED_SGPIO_CLK_DIV_MASK GENMASK(31, 16)
|
||||
#define ASPEED_SGPIO_ENABLE BIT(0)
|
||||
#define ASPEED_SGPIO_PINS_SHIFT 6
|
||||
|
||||
struct aspeed_sgpio_pdata {
|
||||
const u32 pin_mask;
|
||||
};
|
||||
|
||||
struct aspeed_sgpio {
|
||||
struct gpio_chip chip;
|
||||
struct irq_chip intc;
|
||||
struct clk *pclk;
|
||||
spinlock_t lock;
|
||||
void __iomem *base;
|
||||
int irq;
|
||||
int n_sgpio;
|
||||
};
|
||||
|
||||
struct aspeed_sgpio_bank {
|
||||
uint16_t val_regs;
|
||||
uint16_t rdata_reg;
|
||||
uint16_t irq_regs;
|
||||
u16 val_regs;
|
||||
u16 rdata_reg;
|
||||
u16 irq_regs;
|
||||
u16 tolerance_regs;
|
||||
const char names[4][3];
|
||||
};
|
||||
|
||||
@@ -63,19 +56,29 @@ static const struct aspeed_sgpio_bank aspeed_sgpio_banks[] = {
|
||||
.val_regs = 0x0000,
|
||||
.rdata_reg = 0x0070,
|
||||
.irq_regs = 0x0004,
|
||||
.tolerance_regs = 0x0018,
|
||||
.names = { "A", "B", "C", "D" },
|
||||
},
|
||||
{
|
||||
.val_regs = 0x001C,
|
||||
.rdata_reg = 0x0074,
|
||||
.irq_regs = 0x0020,
|
||||
.tolerance_regs = 0x0034,
|
||||
.names = { "E", "F", "G", "H" },
|
||||
},
|
||||
{
|
||||
.val_regs = 0x0038,
|
||||
.rdata_reg = 0x0078,
|
||||
.irq_regs = 0x003C,
|
||||
.names = { "I", "J" },
|
||||
.tolerance_regs = 0x0050,
|
||||
.names = { "I", "J", "K", "L" },
|
||||
},
|
||||
{
|
||||
.val_regs = 0x0090,
|
||||
.rdata_reg = 0x007C,
|
||||
.irq_regs = 0x0094,
|
||||
.tolerance_regs = 0x00A8,
|
||||
.names = { "M", "N", "O", "P" },
|
||||
},
|
||||
};
|
||||
|
||||
@@ -87,6 +90,7 @@ enum aspeed_sgpio_reg {
|
||||
reg_irq_type1,
|
||||
reg_irq_type2,
|
||||
reg_irq_status,
|
||||
reg_tolerance,
|
||||
};
|
||||
|
||||
#define GPIO_VAL_VALUE 0x00
|
||||
@@ -115,15 +119,17 @@ static void __iomem *bank_reg(struct aspeed_sgpio *gpio,
|
||||
return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE2;
|
||||
case reg_irq_status:
|
||||
return gpio->base + bank->irq_regs + GPIO_IRQ_STATUS;
|
||||
case reg_tolerance:
|
||||
return gpio->base + bank->tolerance_regs;
|
||||
default:
|
||||
/* acturally if code runs to here, it's an error case */
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
#define GPIO_BANK(x) ((x % SGPIO_OUTPUT_OFFSET) >> 5)
|
||||
#define GPIO_OFFSET(x) ((x % SGPIO_OUTPUT_OFFSET) & 0x1f)
|
||||
#define GPIO_BIT(x) BIT(GPIO_OFFSET(x))
|
||||
#define GPIO_BANK(x) ((x) >> 6)
|
||||
#define GPIO_OFFSET(x) ((x) & GENMASK(5, 0))
|
||||
#define GPIO_BIT(x) BIT(GPIO_OFFSET(x) >> 1)
|
||||
|
||||
static const struct aspeed_sgpio_bank *to_bank(unsigned int offset)
|
||||
{
|
||||
@@ -138,39 +144,25 @@ static const struct aspeed_sgpio_bank *to_bank(unsigned int offset)
|
||||
static int aspeed_sgpio_init_valid_mask(struct gpio_chip *gc,
|
||||
unsigned long *valid_mask, unsigned int ngpios)
|
||||
{
|
||||
struct aspeed_sgpio *sgpio = gpiochip_get_data(gc);
|
||||
int n = sgpio->n_sgpio;
|
||||
int c = SGPIO_OUTPUT_OFFSET - n;
|
||||
|
||||
WARN_ON(ngpios < MAX_NR_HW_SGPIO * 2);
|
||||
|
||||
/* input GPIOs in the lower range */
|
||||
bitmap_set(valid_mask, 0, n);
|
||||
bitmap_clear(valid_mask, n, c);
|
||||
|
||||
/* output GPIOS above SGPIO_OUTPUT_OFFSET */
|
||||
bitmap_set(valid_mask, SGPIO_OUTPUT_OFFSET, n);
|
||||
bitmap_clear(valid_mask, SGPIO_OUTPUT_OFFSET + n, c);
|
||||
|
||||
bitmap_set(valid_mask, 0, ngpios);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void aspeed_sgpio_irq_init_valid_mask(struct gpio_chip *gc,
|
||||
unsigned long *valid_mask, unsigned int ngpios)
|
||||
{
|
||||
struct aspeed_sgpio *sgpio = gpiochip_get_data(gc);
|
||||
int n = sgpio->n_sgpio;
|
||||
unsigned int i;
|
||||
|
||||
WARN_ON(ngpios < MAX_NR_HW_SGPIO * 2);
|
||||
|
||||
/* input GPIOs in the lower range */
|
||||
bitmap_set(valid_mask, 0, n);
|
||||
bitmap_clear(valid_mask, n, ngpios - n);
|
||||
/* input GPIOs are even bits */
|
||||
for (i = 0; i < ngpios; i++) {
|
||||
if (i % 2)
|
||||
clear_bit(i, valid_mask);
|
||||
}
|
||||
}
|
||||
|
||||
static bool aspeed_sgpio_is_input(unsigned int offset)
|
||||
{
|
||||
return offset < SGPIO_OUTPUT_OFFSET;
|
||||
return !(offset % 2);
|
||||
}
|
||||
|
||||
static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset)
|
||||
@@ -409,14 +401,6 @@ static void aspeed_sgpio_irq_handler(struct irq_desc *desc)
|
||||
chained_irq_exit(ic, desc);
|
||||
}
|
||||
|
||||
static struct irq_chip aspeed_sgpio_irqchip = {
|
||||
.name = "aspeed-sgpio",
|
||||
.irq_ack = aspeed_sgpio_irq_ack,
|
||||
.irq_mask = aspeed_sgpio_irq_mask,
|
||||
.irq_unmask = aspeed_sgpio_irq_unmask,
|
||||
.irq_set_type = aspeed_sgpio_set_type,
|
||||
};
|
||||
|
||||
static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
@@ -439,8 +423,14 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio,
|
||||
iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_status));
|
||||
}
|
||||
|
||||
gpio->intc.name = dev_name(&pdev->dev);
|
||||
gpio->intc.irq_ack = aspeed_sgpio_irq_ack;
|
||||
gpio->intc.irq_mask = aspeed_sgpio_irq_mask;
|
||||
gpio->intc.irq_unmask = aspeed_sgpio_irq_unmask;
|
||||
gpio->intc.irq_set_type = aspeed_sgpio_set_type;
|
||||
|
||||
irq = &gpio->chip.irq;
|
||||
irq->chip = &aspeed_sgpio_irqchip;
|
||||
irq->chip = &gpio->intc;
|
||||
irq->init_valid_mask = aspeed_sgpio_irq_init_valid_mask;
|
||||
irq->handler = handle_bad_irq;
|
||||
irq->default_type = IRQ_TYPE_NONE;
|
||||
@@ -463,9 +453,56 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct aspeed_sgpio_pdata ast2400_sgpio_pdata = {
|
||||
.pin_mask = GENMASK(9, 6),
|
||||
};
|
||||
|
||||
static int aspeed_sgpio_reset_tolerance(struct gpio_chip *chip,
|
||||
unsigned int offset, bool enable)
|
||||
{
|
||||
struct aspeed_sgpio *gpio = gpiochip_get_data(chip);
|
||||
unsigned long flags;
|
||||
void __iomem *reg;
|
||||
u32 val;
|
||||
|
||||
reg = bank_reg(gpio, to_bank(offset), reg_tolerance);
|
||||
|
||||
spin_lock_irqsave(&gpio->lock, flags);
|
||||
|
||||
val = readl(reg);
|
||||
|
||||
if (enable)
|
||||
val |= GPIO_BIT(offset);
|
||||
else
|
||||
val &= ~GPIO_BIT(offset);
|
||||
|
||||
writel(val, reg);
|
||||
|
||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aspeed_sgpio_set_config(struct gpio_chip *chip, unsigned int offset,
|
||||
unsigned long config)
|
||||
{
|
||||
unsigned long param = pinconf_to_config_param(config);
|
||||
u32 arg = pinconf_to_config_argument(config);
|
||||
|
||||
if (param == PIN_CONFIG_PERSIST_STATE)
|
||||
return aspeed_sgpio_reset_tolerance(chip, offset, arg);
|
||||
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static const struct aspeed_sgpio_pdata ast2600_sgpiom_pdata = {
|
||||
.pin_mask = GENMASK(10, 6),
|
||||
};
|
||||
|
||||
static const struct of_device_id aspeed_sgpio_of_table[] = {
|
||||
{ .compatible = "aspeed,ast2400-sgpio" },
|
||||
{ .compatible = "aspeed,ast2500-sgpio" },
|
||||
{ .compatible = "aspeed,ast2400-sgpio", .data = &ast2400_sgpio_pdata, },
|
||||
{ .compatible = "aspeed,ast2500-sgpio", .data = &ast2400_sgpio_pdata, },
|
||||
{ .compatible = "aspeed,ast2600-sgpiom", .data = &ast2600_sgpiom_pdata, },
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -473,10 +510,11 @@ MODULE_DEVICE_TABLE(of, aspeed_sgpio_of_table);
|
||||
|
||||
static int __init aspeed_sgpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
u32 nr_gpios, sgpio_freq, sgpio_clk_div, gpio_cnt_regval, pin_mask;
|
||||
const struct aspeed_sgpio_pdata *pdata;
|
||||
struct aspeed_sgpio *gpio;
|
||||
u32 nr_gpios, sgpio_freq, sgpio_clk_div;
|
||||
int rc;
|
||||
unsigned long apb_freq;
|
||||
int rc;
|
||||
|
||||
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
|
||||
if (!gpio)
|
||||
@@ -486,18 +524,23 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(gpio->base))
|
||||
return PTR_ERR(gpio->base);
|
||||
|
||||
rc = of_property_read_u32(pdev->dev.of_node, "ngpios", &nr_gpios);
|
||||
pdata = device_get_match_data(&pdev->dev);
|
||||
if (!pdata)
|
||||
return -EINVAL;
|
||||
|
||||
pin_mask = pdata->pin_mask;
|
||||
|
||||
rc = device_property_read_u32(&pdev->dev, "ngpios", &nr_gpios);
|
||||
if (rc < 0) {
|
||||
dev_err(&pdev->dev, "Could not read ngpios property\n");
|
||||
return -EINVAL;
|
||||
} else if (nr_gpios > MAX_NR_HW_SGPIO) {
|
||||
dev_err(&pdev->dev, "Number of GPIOs exceeds the maximum of %d: %d\n",
|
||||
MAX_NR_HW_SGPIO, nr_gpios);
|
||||
} else if (nr_gpios % 8) {
|
||||
dev_err(&pdev->dev, "Number of GPIOs not multiple of 8: %d\n",
|
||||
nr_gpios);
|
||||
return -EINVAL;
|
||||
}
|
||||
gpio->n_sgpio = nr_gpios;
|
||||
|
||||
rc = of_property_read_u32(pdev->dev.of_node, "bus-frequency", &sgpio_freq);
|
||||
rc = device_property_read_u32(&pdev->dev, "bus-frequency", &sgpio_freq);
|
||||
if (rc < 0) {
|
||||
dev_err(&pdev->dev, "Could not read bus-frequency property\n");
|
||||
return -EINVAL;
|
||||
@@ -528,15 +571,14 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
|
||||
if (sgpio_clk_div > (1 << 16) - 1)
|
||||
return -EINVAL;
|
||||
|
||||
iowrite32(FIELD_PREP(ASPEED_SGPIO_CLK_DIV_MASK, sgpio_clk_div) |
|
||||
FIELD_PREP(ASPEED_SGPIO_PINS_MASK, (nr_gpios / 8)) |
|
||||
ASPEED_SGPIO_ENABLE,
|
||||
gpio->base + ASPEED_SGPIO_CTRL);
|
||||
gpio_cnt_regval = ((nr_gpios / 8) << ASPEED_SGPIO_PINS_SHIFT) & pin_mask;
|
||||
iowrite32(FIELD_PREP(ASPEED_SGPIO_CLK_DIV_MASK, sgpio_clk_div) | gpio_cnt_regval |
|
||||
ASPEED_SGPIO_ENABLE, gpio->base + ASPEED_SGPIO_CTRL);
|
||||
|
||||
spin_lock_init(&gpio->lock);
|
||||
|
||||
gpio->chip.parent = &pdev->dev;
|
||||
gpio->chip.ngpio = MAX_NR_HW_SGPIO * 2;
|
||||
gpio->chip.ngpio = nr_gpios * 2;
|
||||
gpio->chip.init_valid_mask = aspeed_sgpio_init_valid_mask;
|
||||
gpio->chip.direction_input = aspeed_sgpio_dir_in;
|
||||
gpio->chip.direction_output = aspeed_sgpio_dir_out;
|
||||
@@ -545,7 +587,7 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
|
||||
gpio->chip.free = NULL;
|
||||
gpio->chip.get = aspeed_sgpio_get;
|
||||
gpio->chip.set = aspeed_sgpio_set;
|
||||
gpio->chip.set_config = NULL;
|
||||
gpio->chip.set_config = aspeed_sgpio_set_config;
|
||||
gpio->chip.label = dev_name(&pdev->dev);
|
||||
gpio->chip.base = -1;
|
||||
|
||||
|
||||
@@ -602,49 +602,6 @@ static const struct dev_pm_ops brcmstb_gpio_pm_ops = {
|
||||
.resume_noirq = brcmstb_gpio_resume,
|
||||
};
|
||||
|
||||
static void brcmstb_gpio_set_names(struct device *dev,
|
||||
struct brcmstb_gpio_bank *bank)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
const char **names;
|
||||
int nstrings, base;
|
||||
unsigned int i;
|
||||
|
||||
base = bank->id * MAX_GPIO_PER_BANK;
|
||||
|
||||
nstrings = of_property_count_strings(np, "gpio-line-names");
|
||||
if (nstrings <= base)
|
||||
/* Line names not present */
|
||||
return;
|
||||
|
||||
names = devm_kcalloc(dev, MAX_GPIO_PER_BANK, sizeof(*names),
|
||||
GFP_KERNEL);
|
||||
if (!names)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Make sure to not index beyond the end of the number of descriptors
|
||||
* of the GPIO device.
|
||||
*/
|
||||
for (i = 0; i < bank->width; i++) {
|
||||
const char *name;
|
||||
int ret;
|
||||
|
||||
ret = of_property_read_string_index(np, "gpio-line-names",
|
||||
base + i, &name);
|
||||
if (ret) {
|
||||
if (ret != -ENODATA)
|
||||
dev_err(dev, "unable to name line %d: %d\n",
|
||||
base + i, ret);
|
||||
break;
|
||||
}
|
||||
if (*name)
|
||||
names[i] = name;
|
||||
}
|
||||
|
||||
bank->gc.names = names;
|
||||
}
|
||||
|
||||
static int brcmstb_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@@ -758,6 +715,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
|
||||
gc->of_xlate = brcmstb_gpio_of_xlate;
|
||||
/* not all ngpio lines are valid, will use bank width later */
|
||||
gc->ngpio = MAX_GPIO_PER_BANK;
|
||||
gc->offset = bank->id * MAX_GPIO_PER_BANK;
|
||||
if (priv->parent_irq > 0)
|
||||
gc->to_irq = brcmstb_gpio_to_irq;
|
||||
|
||||
@@ -768,7 +726,6 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
|
||||
need_wakeup_event |= !!__brcmstb_gpio_get_active_irqs(bank);
|
||||
gc->write_reg(reg_base + GIO_MASK(bank->id), 0);
|
||||
|
||||
brcmstb_gpio_set_names(dev, bank);
|
||||
err = gpiochip_add_data(gc, bank);
|
||||
if (err) {
|
||||
dev_err(dev, "Could not add gpiochip for bank %d\n",
|
||||
|
||||
+34
-22
@@ -16,7 +16,6 @@
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_data/gpio-dwapb.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/reset.h>
|
||||
@@ -48,6 +47,7 @@
|
||||
|
||||
#define DWAPB_DRIVER_NAME "gpio-dwapb"
|
||||
#define DWAPB_MAX_PORTS 4
|
||||
#define DWAPB_MAX_GPIOS 32
|
||||
|
||||
#define GPIO_EXT_PORT_STRIDE 0x04 /* register stride 32 bits */
|
||||
#define GPIO_SWPORT_DR_STRIDE 0x0c /* register stride 3*32 bits */
|
||||
@@ -65,6 +65,19 @@
|
||||
|
||||
struct dwapb_gpio;
|
||||
|
||||
struct dwapb_port_property {
|
||||
struct fwnode_handle *fwnode;
|
||||
unsigned int idx;
|
||||
unsigned int ngpio;
|
||||
unsigned int gpio_base;
|
||||
int irq[DWAPB_MAX_GPIOS];
|
||||
};
|
||||
|
||||
struct dwapb_platform_data {
|
||||
struct dwapb_port_property *properties;
|
||||
unsigned int nports;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
/* Store GPIO context across system-wide suspend/resume transitions */
|
||||
struct dwapb_context {
|
||||
@@ -436,21 +449,17 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
|
||||
pirq->irqchip.irq_set_wake = dwapb_irq_set_wake;
|
||||
#endif
|
||||
|
||||
if (!pp->irq_shared) {
|
||||
girq->num_parents = pirq->nr_irqs;
|
||||
girq->parents = pirq->irq;
|
||||
girq->parent_handler_data = gpio;
|
||||
girq->parent_handler = dwapb_irq_handler;
|
||||
} else {
|
||||
/* This will let us handle the parent IRQ in the driver */
|
||||
/*
|
||||
* Intel ACPI-based platforms mostly have the DesignWare APB GPIO
|
||||
* IRQ lane shared between several devices. In that case the parental
|
||||
* IRQ has to be handled in the shared way so to be properly delivered
|
||||
* to all the connected devices.
|
||||
*/
|
||||
if (has_acpi_companion(gpio->dev)) {
|
||||
girq->num_parents = 0;
|
||||
girq->parents = NULL;
|
||||
girq->parent_handler = NULL;
|
||||
|
||||
/*
|
||||
* Request a shared IRQ since where MFD would have devices
|
||||
* using the same irq pin
|
||||
*/
|
||||
err = devm_request_irq(gpio->dev, pp->irq[0],
|
||||
dwapb_irq_handler_mfd,
|
||||
IRQF_SHARED, DWAPB_DRIVER_NAME, gpio);
|
||||
@@ -458,6 +467,11 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
|
||||
dev_err(gpio->dev, "error requesting IRQ\n");
|
||||
goto err_kfree_pirq;
|
||||
}
|
||||
} else {
|
||||
girq->num_parents = pirq->nr_irqs;
|
||||
girq->parents = pirq->irq;
|
||||
girq->parent_handler_data = gpio;
|
||||
girq->parent_handler = dwapb_irq_handler;
|
||||
}
|
||||
|
||||
girq->chip = &pirq->irqchip;
|
||||
@@ -581,9 +595,12 @@ static struct dwapb_platform_data *dwapb_gpio_get_pdata(struct device *dev)
|
||||
pp->ngpio = DWAPB_MAX_GPIOS;
|
||||
}
|
||||
|
||||
pp->irq_shared = false;
|
||||
pp->gpio_base = -1;
|
||||
|
||||
/* For internal use only, new platforms mustn't exercise this */
|
||||
if (is_software_node(fwnode))
|
||||
fwnode_property_read_u32(fwnode, "gpio-base", &pp->gpio_base);
|
||||
|
||||
/*
|
||||
* Only port A can provide interrupts in all configurations of
|
||||
* the IP.
|
||||
@@ -670,17 +687,12 @@ static int dwapb_gpio_probe(struct platform_device *pdev)
|
||||
unsigned int i;
|
||||
struct dwapb_gpio *gpio;
|
||||
int err;
|
||||
struct dwapb_platform_data *pdata;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct dwapb_platform_data *pdata = dev_get_platdata(dev);
|
||||
|
||||
if (!pdata) {
|
||||
pdata = dwapb_gpio_get_pdata(dev);
|
||||
if (IS_ERR(pdata))
|
||||
return PTR_ERR(pdata);
|
||||
}
|
||||
|
||||
if (!pdata->nports)
|
||||
return -ENODEV;
|
||||
pdata = dwapb_gpio_get_pdata(dev);
|
||||
if (IS_ERR(pdata))
|
||||
return PTR_ERR(pdata);
|
||||
|
||||
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
|
||||
if (!gpio)
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright 2009-2012 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||
*
|
||||
* Author: Wu Guoxing <b39297@freescale.com>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
|
||||
#define GPIO_GROUP_NUM 2
|
||||
#define GPIO_NUM_PER_GROUP 8
|
||||
#define GPIO_NUM (GPIO_GROUP_NUM*GPIO_NUM_PER_GROUP)
|
||||
|
||||
struct mc9s08dz60 {
|
||||
struct i2c_client *client;
|
||||
struct gpio_chip chip;
|
||||
};
|
||||
|
||||
static void mc9s_gpio_to_reg_and_bit(int offset, u8 *reg, u8 *bit)
|
||||
{
|
||||
*reg = 0x20 + offset / GPIO_NUM_PER_GROUP;
|
||||
*bit = offset % GPIO_NUM_PER_GROUP;
|
||||
}
|
||||
|
||||
static int mc9s08dz60_get_value(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
u8 reg, bit;
|
||||
s32 value;
|
||||
struct mc9s08dz60 *mc9s = gpiochip_get_data(gc);
|
||||
|
||||
mc9s_gpio_to_reg_and_bit(offset, ®, &bit);
|
||||
value = i2c_smbus_read_byte_data(mc9s->client, reg);
|
||||
|
||||
return (value >= 0) ? (value >> bit) & 0x1 : 0;
|
||||
}
|
||||
|
||||
static int mc9s08dz60_set(struct mc9s08dz60 *mc9s, unsigned offset, int val)
|
||||
{
|
||||
u8 reg, bit;
|
||||
s32 value;
|
||||
|
||||
mc9s_gpio_to_reg_and_bit(offset, ®, &bit);
|
||||
value = i2c_smbus_read_byte_data(mc9s->client, reg);
|
||||
if (value >= 0) {
|
||||
if (val)
|
||||
value |= 1 << bit;
|
||||
else
|
||||
value &= ~(1 << bit);
|
||||
|
||||
return i2c_smbus_write_byte_data(mc9s->client, reg, value);
|
||||
} else
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void mc9s08dz60_set_value(struct gpio_chip *gc, unsigned offset, int val)
|
||||
{
|
||||
struct mc9s08dz60 *mc9s = gpiochip_get_data(gc);
|
||||
|
||||
mc9s08dz60_set(mc9s, offset, val);
|
||||
}
|
||||
|
||||
static int mc9s08dz60_direction_output(struct gpio_chip *gc,
|
||||
unsigned offset, int val)
|
||||
{
|
||||
struct mc9s08dz60 *mc9s = gpiochip_get_data(gc);
|
||||
|
||||
return mc9s08dz60_set(mc9s, offset, val);
|
||||
}
|
||||
|
||||
static int mc9s08dz60_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct mc9s08dz60 *mc9s;
|
||||
|
||||
mc9s = devm_kzalloc(&client->dev, sizeof(*mc9s), GFP_KERNEL);
|
||||
if (!mc9s)
|
||||
return -ENOMEM;
|
||||
|
||||
mc9s->chip.label = client->name;
|
||||
mc9s->chip.base = -1;
|
||||
mc9s->chip.parent = &client->dev;
|
||||
mc9s->chip.owner = THIS_MODULE;
|
||||
mc9s->chip.ngpio = GPIO_NUM;
|
||||
mc9s->chip.can_sleep = true;
|
||||
mc9s->chip.get = mc9s08dz60_get_value;
|
||||
mc9s->chip.set = mc9s08dz60_set_value;
|
||||
mc9s->chip.direction_output = mc9s08dz60_direction_output;
|
||||
mc9s->client = client;
|
||||
i2c_set_clientdata(client, mc9s);
|
||||
|
||||
return devm_gpiochip_add_data(&client->dev, &mc9s->chip, mc9s);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id mc9s08dz60_id[] = {
|
||||
{"mc9s08dz60", 0},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct i2c_driver mc9s08dz60_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "mc9s08dz60",
|
||||
},
|
||||
.probe = mc9s08dz60_probe,
|
||||
.id_table = mc9s08dz60_id,
|
||||
};
|
||||
builtin_i2c_driver(mc9s08dz60_i2c_driver);
|
||||
+11
-38
@@ -155,11 +155,10 @@ static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
/*
|
||||
* Save register configuration and disable interrupts.
|
||||
*/
|
||||
static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
|
||||
static void __maybe_unused ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -185,7 +184,7 @@ static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
|
||||
/*
|
||||
* This function restores the register configuration of the GPIO device.
|
||||
*/
|
||||
static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip)
|
||||
static void __maybe_unused ioh_gpio_restore_reg_conf(struct ioh_gpio *chip)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -207,7 +206,6 @@ static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip)
|
||||
&chip->reg->ioh_sel_reg[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ioh_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
|
||||
{
|
||||
@@ -522,47 +520,23 @@ static void ioh_gpio_remove(struct pci_dev *pdev)
|
||||
kfree(chip);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int ioh_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
static int __maybe_unused ioh_gpio_suspend(struct device *dev)
|
||||
{
|
||||
s32 ret;
|
||||
struct ioh_gpio *chip = pci_get_drvdata(pdev);
|
||||
struct ioh_gpio *chip = dev_get_drvdata(dev);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&chip->spinlock, flags);
|
||||
ioh_gpio_save_reg_conf(chip);
|
||||
spin_unlock_irqrestore(&chip->spinlock, flags);
|
||||
|
||||
ret = pci_save_state(pdev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
pci_disable_device(pdev);
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
ret = pci_enable_wake(pdev, PCI_D0, 1);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ioh_gpio_resume(struct pci_dev *pdev)
|
||||
static int __maybe_unused ioh_gpio_resume(struct device *dev)
|
||||
{
|
||||
s32 ret;
|
||||
struct ioh_gpio *chip = pci_get_drvdata(pdev);
|
||||
struct ioh_gpio *chip = dev_get_drvdata(dev);
|
||||
unsigned long flags;
|
||||
|
||||
ret = pci_enable_wake(pdev, PCI_D0, 0);
|
||||
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret);
|
||||
return ret;
|
||||
}
|
||||
pci_restore_state(pdev);
|
||||
|
||||
spin_lock_irqsave(&chip->spinlock, flags);
|
||||
iowrite32(0x01, &chip->reg->srst);
|
||||
iowrite32(0x00, &chip->reg->srst);
|
||||
@@ -571,10 +545,8 @@ static int ioh_gpio_resume(struct pci_dev *pdev)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define ioh_gpio_suspend NULL
|
||||
#define ioh_gpio_resume NULL
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(ioh_gpio_pm_ops, ioh_gpio_suspend, ioh_gpio_resume);
|
||||
|
||||
static const struct pci_device_id ioh_gpio_pcidev_id[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) },
|
||||
@@ -587,8 +559,9 @@ static struct pci_driver ioh_gpio_driver = {
|
||||
.id_table = ioh_gpio_pcidev_id,
|
||||
.probe = ioh_gpio_probe,
|
||||
.remove = ioh_gpio_remove,
|
||||
.suspend = ioh_gpio_suspend,
|
||||
.resume = ioh_gpio_resume
|
||||
.driver = {
|
||||
.pm = &ioh_gpio_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
module_pci_driver(ioh_gpio_driver);
|
||||
|
||||
+13
-30
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/device.h>
|
||||
@@ -8,6 +7,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
@@ -47,12 +47,10 @@
|
||||
#define YU_GPIO_MODE0_SET 0x54
|
||||
#define YU_GPIO_MODE0_CLEAR 0x58
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
struct mlxbf2_gpio_context_save_regs {
|
||||
u32 gpio_mode0;
|
||||
u32 gpio_mode1;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* BlueField-2 gpio block context structure. */
|
||||
struct mlxbf2_gpio_context {
|
||||
@@ -61,9 +59,7 @@ struct mlxbf2_gpio_context {
|
||||
/* YU GPIO blocks address */
|
||||
void __iomem *gpio_io;
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
struct mlxbf2_gpio_context_save_regs *csave_regs;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* BlueField-2 gpio shared structure. */
|
||||
@@ -73,11 +69,8 @@ struct mlxbf2_gpio_param {
|
||||
struct mutex *lock;
|
||||
};
|
||||
|
||||
static struct resource yu_arm_gpio_lock_res = {
|
||||
.start = YU_ARM_GPIO_LOCK_ADDR,
|
||||
.end = YU_ARM_GPIO_LOCK_ADDR + YU_ARM_GPIO_LOCK_SIZE - 1,
|
||||
.name = "YU_ARM_GPIO_LOCK",
|
||||
};
|
||||
static struct resource yu_arm_gpio_lock_res =
|
||||
DEFINE_RES_MEM_NAMED(YU_ARM_GPIO_LOCK_ADDR, YU_ARM_GPIO_LOCK_SIZE, "YU_ARM_GPIO_LOCK");
|
||||
|
||||
static DEFINE_MUTEX(yu_arm_gpio_lock_mutex);
|
||||
|
||||
@@ -232,7 +225,6 @@ mlxbf2_gpio_probe(struct platform_device *pdev)
|
||||
struct mlxbf2_gpio_context *gs;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct gpio_chip *gc;
|
||||
struct resource *res;
|
||||
unsigned int npins;
|
||||
int ret;
|
||||
|
||||
@@ -241,13 +233,9 @@ mlxbf2_gpio_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
/* YU GPIO block address */
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -ENODEV;
|
||||
|
||||
gs->gpio_io = devm_ioremap(dev, res->start, resource_size(res));
|
||||
if (!gs->gpio_io)
|
||||
return -ENOMEM;
|
||||
gs->gpio_io = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(gs->gpio_io))
|
||||
return PTR_ERR(gs->gpio_io);
|
||||
|
||||
ret = mlxbf2_gpio_get_lock_res(pdev);
|
||||
if (ret) {
|
||||
@@ -284,11 +272,9 @@ mlxbf2_gpio_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int mlxbf2_gpio_suspend(struct platform_device *pdev,
|
||||
pm_message_t state)
|
||||
static int __maybe_unused mlxbf2_gpio_suspend(struct device *dev)
|
||||
{
|
||||
struct mlxbf2_gpio_context *gs = platform_get_drvdata(pdev);
|
||||
struct mlxbf2_gpio_context *gs = dev_get_drvdata(dev);
|
||||
|
||||
gs->csave_regs->gpio_mode0 = readl(gs->gpio_io +
|
||||
YU_GPIO_MODE0);
|
||||
@@ -298,9 +284,9 @@ static int mlxbf2_gpio_suspend(struct platform_device *pdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlxbf2_gpio_resume(struct platform_device *pdev)
|
||||
static int __maybe_unused mlxbf2_gpio_resume(struct device *dev)
|
||||
{
|
||||
struct mlxbf2_gpio_context *gs = platform_get_drvdata(pdev);
|
||||
struct mlxbf2_gpio_context *gs = dev_get_drvdata(dev);
|
||||
|
||||
writel(gs->csave_regs->gpio_mode0, gs->gpio_io +
|
||||
YU_GPIO_MODE0);
|
||||
@@ -309,7 +295,7 @@ static int mlxbf2_gpio_resume(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
static SIMPLE_DEV_PM_OPS(mlxbf2_pm_ops, mlxbf2_gpio_suspend, mlxbf2_gpio_resume);
|
||||
|
||||
static const struct acpi_device_id __maybe_unused mlxbf2_gpio_acpi_match[] = {
|
||||
{ "MLNXBF22", 0 },
|
||||
@@ -320,13 +306,10 @@ MODULE_DEVICE_TABLE(acpi, mlxbf2_gpio_acpi_match);
|
||||
static struct platform_driver mlxbf2_gpio_driver = {
|
||||
.driver = {
|
||||
.name = "mlxbf2_gpio",
|
||||
.acpi_match_table = ACPI_PTR(mlxbf2_gpio_acpi_match),
|
||||
.acpi_match_table = mlxbf2_gpio_acpi_match,
|
||||
.pm = &mlxbf2_pm_ops,
|
||||
},
|
||||
.probe = mlxbf2_gpio_probe,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = mlxbf2_gpio_suspend,
|
||||
.resume = mlxbf2_gpio_resume,
|
||||
#endif
|
||||
};
|
||||
|
||||
module_platform_driver(mlxbf2_gpio_driver);
|
||||
|
||||
@@ -332,7 +332,7 @@ static int mpc8xxx_probe(struct platform_device *pdev)
|
||||
mpc8xxx_gc->regs + GPIO_DIR, NULL,
|
||||
BGPIOF_BIG_ENDIAN);
|
||||
if (ret)
|
||||
goto err;
|
||||
return ret;
|
||||
dev_dbg(&pdev->dev, "GPIO registers are LITTLE endian\n");
|
||||
} else {
|
||||
ret = bgpio_init(gc, &pdev->dev, 4,
|
||||
@@ -342,7 +342,7 @@ static int mpc8xxx_probe(struct platform_device *pdev)
|
||||
BGPIOF_BIG_ENDIAN
|
||||
| BGPIOF_BIG_ENDIAN_BYTE_ORDER);
|
||||
if (ret)
|
||||
goto err;
|
||||
return ret;
|
||||
dev_dbg(&pdev->dev, "GPIO registers are BIG endian\n");
|
||||
}
|
||||
|
||||
@@ -380,11 +380,11 @@ static int mpc8xxx_probe(struct platform_device *pdev)
|
||||
is_acpi_node(fwnode))
|
||||
gc->write_reg(mpc8xxx_gc->regs + GPIO_IBE, 0xffffffff);
|
||||
|
||||
ret = gpiochip_add_data(gc, mpc8xxx_gc);
|
||||
ret = devm_gpiochip_add_data(&pdev->dev, gc, mpc8xxx_gc);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"GPIO chip registration failed with status %d\n", ret);
|
||||
goto err;
|
||||
return ret;
|
||||
}
|
||||
|
||||
mpc8xxx_gc->irqn = platform_get_irq(pdev, 0);
|
||||
@@ -416,7 +416,7 @@ static int mpc8xxx_probe(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
err:
|
||||
iounmap(mpc8xxx_gc->regs);
|
||||
irq_domain_remove(mpc8xxx_gc->irq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -429,9 +429,6 @@ static int mpc8xxx_remove(struct platform_device *pdev)
|
||||
irq_domain_remove(mpc8xxx_gc->irq);
|
||||
}
|
||||
|
||||
gpiochip_remove(&mpc8xxx_gc->gc);
|
||||
iounmap(mpc8xxx_gc->regs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -239,6 +239,7 @@ mediatek_gpio_bank_probe(struct device *dev,
|
||||
if (!rg->chip.label)
|
||||
return -ENOMEM;
|
||||
|
||||
rg->chip.offset = bank * MTK_BANK_WIDTH;
|
||||
rg->irq_chip.name = dev_name(dev);
|
||||
rg->irq_chip.parent_device = dev;
|
||||
rg->irq_chip.irq_unmask = mediatek_gpio_irq_unmask;
|
||||
|
||||
@@ -564,9 +564,9 @@ static int gpio_rcar_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
if (p->info.has_inen) {
|
||||
pm_runtime_get_sync(p->dev);
|
||||
pm_runtime_get_sync(dev);
|
||||
gpio_rcar_enable_inputs(p);
|
||||
pm_runtime_put(p->dev);
|
||||
pm_runtime_put(dev);
|
||||
}
|
||||
|
||||
dev_info(dev, "driving %d GPIOs\n", npins);
|
||||
|
||||
@@ -607,15 +607,21 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
|
||||
if (!gpio)
|
||||
return -ENOMEM;
|
||||
|
||||
gpio->soc = of_device_get_match_data(&pdev->dev);
|
||||
gpio->soc = device_get_match_data(&pdev->dev);
|
||||
|
||||
gpio->secure = devm_platform_ioremap_resource_byname(pdev, "security");
|
||||
if (IS_ERR(gpio->secure))
|
||||
return PTR_ERR(gpio->secure);
|
||||
if (IS_ERR(gpio->secure)) {
|
||||
gpio->secure = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(gpio->secure))
|
||||
return PTR_ERR(gpio->secure);
|
||||
}
|
||||
|
||||
gpio->base = devm_platform_ioremap_resource_byname(pdev, "gpio");
|
||||
if (IS_ERR(gpio->base))
|
||||
return PTR_ERR(gpio->base);
|
||||
if (IS_ERR(gpio->base)) {
|
||||
gpio->base = devm_platform_ioremap_resource(pdev, 1);
|
||||
if (IS_ERR(gpio->base))
|
||||
return PTR_ERR(gpio->base);
|
||||
}
|
||||
|
||||
err = platform_irq_count(pdev);
|
||||
if (err < 0)
|
||||
@@ -677,11 +683,13 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
|
||||
|
||||
gpio->gpio.names = (const char * const *)names;
|
||||
|
||||
#if defined(CONFIG_OF_GPIO)
|
||||
gpio->gpio.of_node = pdev->dev.of_node;
|
||||
gpio->gpio.of_gpio_n_cells = 2;
|
||||
gpio->gpio.of_xlate = tegra186_gpio_of_xlate;
|
||||
#endif /* CONFIG_OF_GPIO */
|
||||
|
||||
gpio->intc.name = pdev->dev.of_node->name;
|
||||
gpio->intc.name = dev_name(&pdev->dev);
|
||||
gpio->intc.irq_ack = tegra186_irq_ack;
|
||||
gpio->intc.irq_mask = tegra186_irq_mask;
|
||||
gpio->intc.irq_unmask = tegra186_irq_unmask;
|
||||
@@ -893,10 +901,20 @@ static const struct of_device_id tegra186_gpio_of_match[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra186_gpio_of_match);
|
||||
|
||||
static const struct acpi_device_id tegra186_gpio_acpi_match[] = {
|
||||
{ .id = "NVDA0108", .driver_data = (kernel_ulong_t)&tegra186_main_soc },
|
||||
{ .id = "NVDA0208", .driver_data = (kernel_ulong_t)&tegra186_aon_soc },
|
||||
{ .id = "NVDA0308", .driver_data = (kernel_ulong_t)&tegra194_main_soc },
|
||||
{ .id = "NVDA0408", .driver_data = (kernel_ulong_t)&tegra194_aon_soc },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, tegra186_gpio_acpi_match);
|
||||
|
||||
static struct platform_driver tegra186_gpio_driver = {
|
||||
.driver = {
|
||||
.name = "tegra186-gpio",
|
||||
.of_match_table = tegra186_gpio_of_match,
|
||||
.acpi_match_table = tegra186_gpio_acpi_match,
|
||||
},
|
||||
.probe = tegra186_gpio_probe,
|
||||
};
|
||||
|
||||
@@ -404,11 +404,10 @@ static int vprbrd_gpio_probe(struct platform_device *pdev)
|
||||
vb_gpio->gpioa.get = vprbrd_gpioa_get;
|
||||
vb_gpio->gpioa.direction_input = vprbrd_gpioa_direction_input;
|
||||
vb_gpio->gpioa.direction_output = vprbrd_gpioa_direction_output;
|
||||
|
||||
ret = devm_gpiochip_add_data(&pdev->dev, &vb_gpio->gpioa, vb_gpio);
|
||||
if (ret < 0) {
|
||||
dev_err(vb_gpio->gpioa.parent, "could not add gpio a");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* registering gpio b */
|
||||
vb_gpio->gpiob.label = "viperboard gpio b";
|
||||
@@ -421,15 +420,8 @@ static int vprbrd_gpio_probe(struct platform_device *pdev)
|
||||
vb_gpio->gpiob.get = vprbrd_gpiob_get;
|
||||
vb_gpio->gpiob.direction_input = vprbrd_gpiob_direction_input;
|
||||
vb_gpio->gpiob.direction_output = vprbrd_gpiob_direction_output;
|
||||
ret = devm_gpiochip_add_data(&pdev->dev, &vb_gpio->gpiob, vb_gpio);
|
||||
if (ret < 0) {
|
||||
dev_err(vb_gpio->gpiob.parent, "could not add gpio b");
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, vb_gpio);
|
||||
|
||||
return ret;
|
||||
return devm_gpiochip_add_data(&pdev->dev, &vb_gpio->gpiob, vb_gpio);
|
||||
}
|
||||
|
||||
static struct platform_driver vprbrd_gpio_driver = {
|
||||
|
||||
@@ -0,0 +1,374 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* GPIO driver for virtio-based virtual GPIO controllers
|
||||
*
|
||||
* Copyright (C) 2021 metux IT consult
|
||||
* Enrico Weigelt, metux IT consult <info@metux.net>
|
||||
*
|
||||
* Copyright (C) 2021 Linaro.
|
||||
* Viresh Kumar <viresh.kumar@linaro.org>
|
||||
*/
|
||||
|
||||
#include <linux/completion.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/virtio_config.h>
|
||||
#include <uapi/linux/virtio_gpio.h>
|
||||
#include <uapi/linux/virtio_ids.h>
|
||||
|
||||
struct virtio_gpio_line {
|
||||
struct mutex lock; /* Protects line operation */
|
||||
struct completion completion;
|
||||
struct virtio_gpio_request req ____cacheline_aligned;
|
||||
struct virtio_gpio_response res ____cacheline_aligned;
|
||||
unsigned int rxlen;
|
||||
};
|
||||
|
||||
struct virtio_gpio {
|
||||
struct virtio_device *vdev;
|
||||
struct mutex lock; /* Protects virtqueue operation */
|
||||
struct gpio_chip gc;
|
||||
struct virtio_gpio_line *lines;
|
||||
struct virtqueue *request_vq;
|
||||
};
|
||||
|
||||
static int _virtio_gpio_req(struct virtio_gpio *vgpio, u16 type, u16 gpio,
|
||||
u8 txvalue, u8 *rxvalue, void *response, u32 rxlen)
|
||||
{
|
||||
struct virtio_gpio_line *line = &vgpio->lines[gpio];
|
||||
struct virtio_gpio_request *req = &line->req;
|
||||
struct virtio_gpio_response *res = response;
|
||||
struct scatterlist *sgs[2], req_sg, res_sg;
|
||||
struct device *dev = &vgpio->vdev->dev;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Prevent concurrent requests for the same line since we have
|
||||
* pre-allocated request/response buffers for each GPIO line. Moreover
|
||||
* Linux always accesses a GPIO line sequentially, so this locking shall
|
||||
* always go through without any delays.
|
||||
*/
|
||||
mutex_lock(&line->lock);
|
||||
|
||||
req->type = cpu_to_le16(type);
|
||||
req->gpio = cpu_to_le16(gpio);
|
||||
req->value = cpu_to_le32(txvalue);
|
||||
|
||||
sg_init_one(&req_sg, req, sizeof(*req));
|
||||
sg_init_one(&res_sg, res, rxlen);
|
||||
sgs[0] = &req_sg;
|
||||
sgs[1] = &res_sg;
|
||||
|
||||
line->rxlen = 0;
|
||||
reinit_completion(&line->completion);
|
||||
|
||||
/*
|
||||
* Virtqueue callers need to ensure they don't call its APIs with other
|
||||
* virtqueue operations at the same time.
|
||||
*/
|
||||
mutex_lock(&vgpio->lock);
|
||||
ret = virtqueue_add_sgs(vgpio->request_vq, sgs, 1, 1, line, GFP_KERNEL);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to add request to vq\n");
|
||||
mutex_unlock(&vgpio->lock);
|
||||
goto out;
|
||||
}
|
||||
|
||||
virtqueue_kick(vgpio->request_vq);
|
||||
mutex_unlock(&vgpio->lock);
|
||||
|
||||
if (!wait_for_completion_timeout(&line->completion, HZ)) {
|
||||
dev_err(dev, "GPIO operation timed out\n");
|
||||
ret = -ETIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (unlikely(res->status != VIRTIO_GPIO_STATUS_OK)) {
|
||||
dev_err(dev, "GPIO request failed: %d\n", gpio);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (unlikely(line->rxlen != rxlen)) {
|
||||
dev_err(dev, "GPIO operation returned incorrect len (%u : %u)\n",
|
||||
rxlen, line->rxlen);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (rxvalue)
|
||||
*rxvalue = res->value;
|
||||
|
||||
out:
|
||||
mutex_unlock(&line->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int virtio_gpio_req(struct virtio_gpio *vgpio, u16 type, u16 gpio,
|
||||
u8 txvalue, u8 *rxvalue)
|
||||
{
|
||||
struct virtio_gpio_line *line = &vgpio->lines[gpio];
|
||||
struct virtio_gpio_response *res = &line->res;
|
||||
|
||||
return _virtio_gpio_req(vgpio, type, gpio, txvalue, rxvalue, res,
|
||||
sizeof(*res));
|
||||
}
|
||||
|
||||
static void virtio_gpio_free(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct virtio_gpio *vgpio = gpiochip_get_data(gc);
|
||||
|
||||
virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_DIRECTION, gpio,
|
||||
VIRTIO_GPIO_DIRECTION_NONE, NULL);
|
||||
}
|
||||
|
||||
static int virtio_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct virtio_gpio *vgpio = gpiochip_get_data(gc);
|
||||
u8 direction;
|
||||
int ret;
|
||||
|
||||
ret = virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_GET_DIRECTION, gpio, 0,
|
||||
&direction);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (direction) {
|
||||
case VIRTIO_GPIO_DIRECTION_IN:
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
case VIRTIO_GPIO_DIRECTION_OUT:
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int virtio_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct virtio_gpio *vgpio = gpiochip_get_data(gc);
|
||||
|
||||
return virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_DIRECTION, gpio,
|
||||
VIRTIO_GPIO_DIRECTION_IN, NULL);
|
||||
}
|
||||
|
||||
static int virtio_gpio_direction_output(struct gpio_chip *gc, unsigned int gpio,
|
||||
int value)
|
||||
{
|
||||
struct virtio_gpio *vgpio = gpiochip_get_data(gc);
|
||||
int ret;
|
||||
|
||||
ret = virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_VALUE, gpio, value, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_DIRECTION, gpio,
|
||||
VIRTIO_GPIO_DIRECTION_OUT, NULL);
|
||||
}
|
||||
|
||||
static int virtio_gpio_get(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct virtio_gpio *vgpio = gpiochip_get_data(gc);
|
||||
u8 value;
|
||||
int ret;
|
||||
|
||||
ret = virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_GET_VALUE, gpio, 0, &value);
|
||||
return ret ? ret : value;
|
||||
}
|
||||
|
||||
static void virtio_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value)
|
||||
{
|
||||
struct virtio_gpio *vgpio = gpiochip_get_data(gc);
|
||||
|
||||
virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_VALUE, gpio, value, NULL);
|
||||
}
|
||||
|
||||
static void virtio_gpio_request_vq(struct virtqueue *vq)
|
||||
{
|
||||
struct virtio_gpio_line *line;
|
||||
unsigned int len;
|
||||
|
||||
do {
|
||||
line = virtqueue_get_buf(vq, &len);
|
||||
if (!line)
|
||||
return;
|
||||
|
||||
line->rxlen = len;
|
||||
complete(&line->completion);
|
||||
} while (1);
|
||||
}
|
||||
|
||||
static void virtio_gpio_free_vqs(struct virtio_device *vdev)
|
||||
{
|
||||
vdev->config->reset(vdev);
|
||||
vdev->config->del_vqs(vdev);
|
||||
}
|
||||
|
||||
static int virtio_gpio_alloc_vqs(struct virtio_gpio *vgpio,
|
||||
struct virtio_device *vdev)
|
||||
{
|
||||
const char * const names[] = { "requestq" };
|
||||
vq_callback_t *cbs[] = {
|
||||
virtio_gpio_request_vq,
|
||||
};
|
||||
struct virtqueue *vqs[1] = { NULL };
|
||||
int ret;
|
||||
|
||||
ret = virtio_find_vqs(vdev, 1, vqs, cbs, names, NULL);
|
||||
if (ret) {
|
||||
dev_err(&vdev->dev, "failed to find vqs: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!vqs[0]) {
|
||||
dev_err(&vdev->dev, "failed to find requestq vq\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
vgpio->request_vq = vqs[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char **virtio_gpio_get_names(struct virtio_gpio *vgpio,
|
||||
u32 gpio_names_size, u16 ngpio)
|
||||
{
|
||||
struct virtio_gpio_response_get_names *res;
|
||||
struct device *dev = &vgpio->vdev->dev;
|
||||
u8 *gpio_names, *str;
|
||||
const char **names;
|
||||
int i, ret, len;
|
||||
|
||||
if (!gpio_names_size)
|
||||
return NULL;
|
||||
|
||||
len = sizeof(*res) + gpio_names_size;
|
||||
res = devm_kzalloc(dev, len, GFP_KERNEL);
|
||||
if (!res)
|
||||
return NULL;
|
||||
gpio_names = res->value;
|
||||
|
||||
ret = _virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_GET_NAMES, 0, 0, NULL,
|
||||
res, len);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get GPIO names: %d\n", ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
names = devm_kcalloc(dev, ngpio, sizeof(*names), GFP_KERNEL);
|
||||
if (!names)
|
||||
return NULL;
|
||||
|
||||
/* NULL terminate the string instead of checking it */
|
||||
gpio_names[gpio_names_size - 1] = '\0';
|
||||
|
||||
for (i = 0, str = gpio_names; i < ngpio; i++) {
|
||||
names[i] = str;
|
||||
str += strlen(str) + 1; /* zero-length strings are allowed */
|
||||
|
||||
if (str > gpio_names + gpio_names_size) {
|
||||
dev_err(dev, "gpio_names block is too short (%d)\n", i);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
static int virtio_gpio_probe(struct virtio_device *vdev)
|
||||
{
|
||||
struct virtio_gpio_config config;
|
||||
struct device *dev = &vdev->dev;
|
||||
struct virtio_gpio *vgpio;
|
||||
u32 gpio_names_size;
|
||||
u16 ngpio;
|
||||
int ret, i;
|
||||
|
||||
vgpio = devm_kzalloc(dev, sizeof(*vgpio), GFP_KERNEL);
|
||||
if (!vgpio)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Read configuration */
|
||||
virtio_cread_bytes(vdev, 0, &config, sizeof(config));
|
||||
gpio_names_size = le32_to_cpu(config.gpio_names_size);
|
||||
ngpio = le16_to_cpu(config.ngpio);
|
||||
if (!ngpio) {
|
||||
dev_err(dev, "Number of GPIOs can't be zero\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vgpio->lines = devm_kcalloc(dev, ngpio, sizeof(*vgpio->lines), GFP_KERNEL);
|
||||
if (!vgpio->lines)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < ngpio; i++) {
|
||||
mutex_init(&vgpio->lines[i].lock);
|
||||
init_completion(&vgpio->lines[i].completion);
|
||||
}
|
||||
|
||||
mutex_init(&vgpio->lock);
|
||||
vdev->priv = vgpio;
|
||||
|
||||
vgpio->vdev = vdev;
|
||||
vgpio->gc.free = virtio_gpio_free;
|
||||
vgpio->gc.get_direction = virtio_gpio_get_direction;
|
||||
vgpio->gc.direction_input = virtio_gpio_direction_input;
|
||||
vgpio->gc.direction_output = virtio_gpio_direction_output;
|
||||
vgpio->gc.get = virtio_gpio_get;
|
||||
vgpio->gc.set = virtio_gpio_set;
|
||||
vgpio->gc.ngpio = ngpio;
|
||||
vgpio->gc.base = -1; /* Allocate base dynamically */
|
||||
vgpio->gc.label = dev_name(dev);
|
||||
vgpio->gc.parent = dev;
|
||||
vgpio->gc.owner = THIS_MODULE;
|
||||
vgpio->gc.can_sleep = true;
|
||||
|
||||
ret = virtio_gpio_alloc_vqs(vgpio, vdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Mark the device ready to perform operations from within probe() */
|
||||
virtio_device_ready(vdev);
|
||||
|
||||
vgpio->gc.names = virtio_gpio_get_names(vgpio, gpio_names_size, ngpio);
|
||||
|
||||
ret = gpiochip_add_data(&vgpio->gc, vgpio);
|
||||
if (ret) {
|
||||
virtio_gpio_free_vqs(vdev);
|
||||
dev_err(dev, "Failed to add virtio-gpio controller\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void virtio_gpio_remove(struct virtio_device *vdev)
|
||||
{
|
||||
struct virtio_gpio *vgpio = vdev->priv;
|
||||
|
||||
gpiochip_remove(&vgpio->gc);
|
||||
virtio_gpio_free_vqs(vdev);
|
||||
}
|
||||
|
||||
static const struct virtio_device_id id_table[] = {
|
||||
{ VIRTIO_ID_GPIO, VIRTIO_DEV_ANY_ID },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(virtio, id_table);
|
||||
|
||||
static struct virtio_driver virtio_gpio_driver = {
|
||||
.id_table = id_table,
|
||||
.probe = virtio_gpio_probe,
|
||||
.remove = virtio_gpio_remove,
|
||||
.driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
module_virtio_driver(virtio_gpio_driver);
|
||||
|
||||
MODULE_AUTHOR("Enrico Weigelt, metux IT consult <info@metux.net>");
|
||||
MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
|
||||
MODULE_DESCRIPTION("VirtIO GPIO driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -145,7 +145,7 @@ EXPORT_SYMBOL_GPL(devm_gpiod_get_index);
|
||||
* In case of error an ERR_PTR() is returned.
|
||||
*/
|
||||
struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
|
||||
struct device_node *node,
|
||||
const struct device_node *node,
|
||||
const char *propname, int index,
|
||||
enum gpiod_flags dflags,
|
||||
const char *label)
|
||||
|
||||
@@ -122,7 +122,7 @@ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip,
|
||||
bool of_gpio_need_valid_mask(const struct gpio_chip *gc)
|
||||
{
|
||||
int size;
|
||||
struct device_node *np = gc->of_node;
|
||||
const struct device_node *np = gc->of_node;
|
||||
|
||||
size = of_property_count_u32_elems(np, "gpio-reserved-ranges");
|
||||
if (size > 0 && size % 2 == 0)
|
||||
@@ -130,7 +130,7 @@ bool of_gpio_need_valid_mask(const struct gpio_chip *gc)
|
||||
return false;
|
||||
}
|
||||
|
||||
static void of_gpio_flags_quirks(struct device_node *np,
|
||||
static void of_gpio_flags_quirks(const struct device_node *np,
|
||||
const char *propname,
|
||||
enum of_gpio_flags *flags,
|
||||
int index)
|
||||
@@ -236,7 +236,7 @@ static void of_gpio_flags_quirks(struct device_node *np,
|
||||
* value on the error condition. If @flags is not NULL the function also fills
|
||||
* in flags for the GPIO.
|
||||
*/
|
||||
static struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
|
||||
static struct gpio_desc *of_get_named_gpiod_flags(const struct device_node *np,
|
||||
const char *propname, int index, enum of_gpio_flags *flags)
|
||||
{
|
||||
struct of_phandle_args gpiospec;
|
||||
@@ -275,7 +275,7 @@ out:
|
||||
return desc;
|
||||
}
|
||||
|
||||
int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
|
||||
int of_get_named_gpio_flags(const struct device_node *np, const char *list_name,
|
||||
int index, enum of_gpio_flags *flags)
|
||||
{
|
||||
struct gpio_desc *desc;
|
||||
@@ -303,7 +303,7 @@ EXPORT_SYMBOL_GPL(of_get_named_gpio_flags);
|
||||
*
|
||||
* In case of error an ERR_PTR() is returned.
|
||||
*/
|
||||
struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
|
||||
struct gpio_desc *gpiod_get_from_of_node(const struct device_node *node,
|
||||
const char *propname, int index,
|
||||
enum gpiod_flags dflags,
|
||||
const char *label)
|
||||
@@ -373,7 +373,7 @@ static struct gpio_desc *of_find_spi_gpio(struct device *dev, const char *con_id
|
||||
enum of_gpio_flags *of_flags)
|
||||
{
|
||||
char prop_name[32]; /* 32 is max size of property name */
|
||||
struct device_node *np = dev->of_node;
|
||||
const struct device_node *np = dev->of_node;
|
||||
struct gpio_desc *desc;
|
||||
|
||||
/*
|
||||
@@ -404,7 +404,7 @@ static struct gpio_desc *of_find_spi_cs_gpio(struct device *dev,
|
||||
unsigned int idx,
|
||||
unsigned long *flags)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
const struct device_node *np = dev->of_node;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_SPI_MASTER))
|
||||
return ERR_PTR(-ENOENT);
|
||||
@@ -440,7 +440,7 @@ static struct gpio_desc *of_find_regulator_gpio(struct device *dev, const char *
|
||||
"wlf,ldo1ena", /* WM8994 */
|
||||
"wlf,ldo2ena", /* WM8994 */
|
||||
};
|
||||
struct device_node *np = dev->of_node;
|
||||
const struct device_node *np = dev->of_node;
|
||||
struct gpio_desc *desc;
|
||||
int i;
|
||||
|
||||
|
||||
+27
-5
@@ -382,10 +382,18 @@ static int devprop_gpiochip_set_names(struct gpio_chip *chip)
|
||||
if (count < 0)
|
||||
return 0;
|
||||
|
||||
if (count > gdev->ngpio) {
|
||||
dev_warn(&gdev->dev, "gpio-line-names is length %d but should be at most length %d",
|
||||
count, gdev->ngpio);
|
||||
count = gdev->ngpio;
|
||||
/*
|
||||
* When offset is set in the driver side we assume the driver internally
|
||||
* is using more than one gpiochip per the same device. We have to stop
|
||||
* setting friendly names if the specified ones with 'gpio-line-names'
|
||||
* are less than the offset in the device itself. This means all the
|
||||
* lines are not present for every single pin within all the internal
|
||||
* gpiochips.
|
||||
*/
|
||||
if (count <= chip->offset) {
|
||||
dev_warn(&gdev->dev, "gpio-line-names too short (length %d), cannot map names for the gpiochip at offset %u\n",
|
||||
count, chip->offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
names = kcalloc(count, sizeof(*names), GFP_KERNEL);
|
||||
@@ -400,8 +408,22 @@ static int devprop_gpiochip_set_names(struct gpio_chip *chip)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* When more that one gpiochip per device is used, 'count' can
|
||||
* contain at most number gpiochips x chip->ngpio. We have to
|
||||
* correctly distribute all defined lines taking into account
|
||||
* chip->offset as starting point from where we will assign
|
||||
* the names to pins from the 'names' array. Since property
|
||||
* 'gpio-line-names' cannot contains gaps, we have to be sure
|
||||
* we only assign those pins that really exists since chip->ngpio
|
||||
* can be different of the chip->offset.
|
||||
*/
|
||||
count = (count > chip->offset) ? count - chip->offset : count;
|
||||
if (count > chip->ngpio)
|
||||
count = chip->ngpio;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
gdev->descs[i].name = names[i];
|
||||
gdev->descs[i].name = names[chip->offset + i];
|
||||
|
||||
kfree(names);
|
||||
|
||||
|
||||
@@ -2199,5 +2199,33 @@ config MFD_INTEL_M10_BMC
|
||||
additional drivers must be enabled in order to use the functionality
|
||||
of the device.
|
||||
|
||||
config MFD_RSMU_I2C
|
||||
tristate "Renesas Synchronization Management Unit with I2C"
|
||||
depends on I2C && OF
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
help
|
||||
Support for the Renesas Synchronization Management Unit, such as
|
||||
Clockmatrix and 82P33XXX series. This option supports I2C as
|
||||
the control interface.
|
||||
|
||||
This driver provides common support for accessing the device.
|
||||
Additional drivers must be enabled in order to use the functionality
|
||||
of the device.
|
||||
|
||||
config MFD_RSMU_SPI
|
||||
tristate "Renesas Synchronization Management Unit with SPI"
|
||||
depends on SPI && OF
|
||||
select MFD_CORE
|
||||
select REGMAP_SPI
|
||||
help
|
||||
Support for the Renesas Synchronization Management Unit, such as
|
||||
Clockmatrix and 82P33XXX series. This option supports SPI as
|
||||
the control interface.
|
||||
|
||||
This driver provides common support for accessing the device.
|
||||
Additional drivers must be enabled in order to use the functionality
|
||||
of the device.
|
||||
|
||||
endmenu
|
||||
endif
|
||||
|
||||
@@ -273,3 +273,8 @@ obj-$(CONFIG_MFD_INTEL_M10_BMC) += intel-m10-bmc.o
|
||||
|
||||
obj-$(CONFIG_MFD_ATC260X) += atc260x-core.o
|
||||
obj-$(CONFIG_MFD_ATC260X_I2C) += atc260x-i2c.o
|
||||
|
||||
rsmu-i2c-objs := rsmu_core.o rsmu_i2c.o
|
||||
rsmu-spi-objs := rsmu_core.o rsmu_spi.o
|
||||
obj-$(CONFIG_MFD_RSMU_I2C) += rsmu-i2c.o
|
||||
obj-$(CONFIG_MFD_RSMU_SPI) += rsmu-spi.o
|
||||
|
||||
@@ -485,7 +485,7 @@ static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
|
||||
if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F)
|
||||
line += 1;
|
||||
|
||||
handle_nested_irq(irq_create_mapping(ab8500->domain, line));
|
||||
handle_nested_irq(irq_find_mapping(ab8500->domain, line));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
+15
-1
@@ -125,12 +125,13 @@ static const struct regmap_range axp288_writeable_ranges[] = {
|
||||
|
||||
static const struct regmap_range axp288_volatile_ranges[] = {
|
||||
regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP288_POWER_REASON),
|
||||
regmap_reg_range(AXP22X_PWR_OUT_CTRL1, AXP22X_ALDO3_V_OUT),
|
||||
regmap_reg_range(AXP288_BC_GLOBAL, AXP288_BC_GLOBAL),
|
||||
regmap_reg_range(AXP288_BC_DET_STAT, AXP20X_VBUS_IPSOUT_MGMT),
|
||||
regmap_reg_range(AXP20X_CHRG_BAK_CTRL, AXP20X_CHRG_BAK_CTRL),
|
||||
regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L),
|
||||
regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL),
|
||||
regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
|
||||
regmap_reg_range(AXP20X_GPIO1_CTRL, AXP22X_GPIO_STATE),
|
||||
regmap_reg_range(AXP288_RT_BATT_V_H, AXP288_RT_BATT_V_L),
|
||||
regmap_reg_range(AXP20X_FG_RES, AXP288_FG_CC_CAP_REG),
|
||||
};
|
||||
@@ -699,6 +700,18 @@ static const struct resource axp288_charger_resources[] = {
|
||||
DEFINE_RES_IRQ(AXP288_IRQ_CBTO),
|
||||
};
|
||||
|
||||
static const char * const axp288_fuel_gauge_suppliers[] = { "axp288_charger" };
|
||||
|
||||
static const struct property_entry axp288_fuel_gauge_properties[] = {
|
||||
PROPERTY_ENTRY_STRING_ARRAY("supplied-from", axp288_fuel_gauge_suppliers),
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct software_node axp288_fuel_gauge_sw_node = {
|
||||
.name = "axp288_fuel_gauge",
|
||||
.properties = axp288_fuel_gauge_properties,
|
||||
};
|
||||
|
||||
static const struct mfd_cell axp288_cells[] = {
|
||||
{
|
||||
.name = "axp288_adc",
|
||||
@@ -716,6 +729,7 @@ static const struct mfd_cell axp288_cells[] = {
|
||||
.name = "axp288_fuel_gauge",
|
||||
.num_resources = ARRAY_SIZE(axp288_fuel_gauge_resources),
|
||||
.resources = axp288_fuel_gauge_resources,
|
||||
.swnode = &axp288_fuel_gauge_sw_node,
|
||||
}, {
|
||||
.name = "axp221-pek",
|
||||
.num_resources = ARRAY_SIZE(axp288_power_button_resources),
|
||||
|
||||
+12
-13
@@ -37,7 +37,7 @@
|
||||
#include <linux/regulator/db8500-prcmu.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/platform_data/ux500_wdt.h>
|
||||
#include "dbx500-prcmu-regs.h"
|
||||
#include "db8500-prcmu-regs.h"
|
||||
|
||||
/* Index of different voltages to be used when accessing AVSData */
|
||||
#define PRCM_AVS_BASE 0x2FC
|
||||
@@ -1622,22 +1622,20 @@ static long round_clock_rate(u8 clock, unsigned long rate)
|
||||
}
|
||||
|
||||
static const unsigned long db8500_armss_freqs[] = {
|
||||
200000000,
|
||||
400000000,
|
||||
800000000,
|
||||
199680000,
|
||||
399360000,
|
||||
798720000,
|
||||
998400000
|
||||
};
|
||||
|
||||
/* The DB8520 has slightly higher ARMSS max frequency */
|
||||
static const unsigned long db8520_armss_freqs[] = {
|
||||
200000000,
|
||||
400000000,
|
||||
800000000,
|
||||
199680000,
|
||||
399360000,
|
||||
798720000,
|
||||
1152000000
|
||||
};
|
||||
|
||||
|
||||
|
||||
static long round_armss_rate(unsigned long rate)
|
||||
{
|
||||
unsigned long freq = 0;
|
||||
@@ -2567,14 +2565,16 @@ static char *fw_project_name(u32 project)
|
||||
return "U8500 C4";
|
||||
case PRCMU_FW_PROJECT_U9500_MBL:
|
||||
return "U9500 MBL";
|
||||
case PRCMU_FW_PROJECT_U8500_MBL:
|
||||
return "U8500 MBL";
|
||||
case PRCMU_FW_PROJECT_U8500_SSG1:
|
||||
return "U8500 Samsung 1";
|
||||
case PRCMU_FW_PROJECT_U8500_MBL2:
|
||||
return "U8500 MBL2";
|
||||
case PRCMU_FW_PROJECT_U8520:
|
||||
return "U8520 MBL";
|
||||
case PRCMU_FW_PROJECT_U8420:
|
||||
return "U8420";
|
||||
case PRCMU_FW_PROJECT_U8500_SSG2:
|
||||
return "U8500 Samsung 2";
|
||||
case PRCMU_FW_PROJECT_U8420_SYSCLK:
|
||||
return "U8420-sysclk";
|
||||
case PRCMU_FW_PROJECT_U9540:
|
||||
@@ -2951,14 +2951,13 @@ static const struct mfd_cell common_prcmu_devs[] = {
|
||||
.pdata_size = sizeof(db8500_wdt_pdata),
|
||||
.id = -1,
|
||||
},
|
||||
MFD_CELL_NAME("db8500-cpuidle"),
|
||||
};
|
||||
|
||||
static const struct mfd_cell db8500_prcmu_devs[] = {
|
||||
MFD_CELL_OF("db8500-prcmu-regulators", NULL,
|
||||
&db8500_regulators, sizeof(db8500_regulators), 0,
|
||||
"stericsson,db8500-prcmu-regulator"),
|
||||
MFD_CELL_OF("cpuidle-dbx500",
|
||||
NULL, NULL, 0, 0, "stericsson,cpuidle-dbx500"),
|
||||
MFD_CELL_OF("db8500-thermal",
|
||||
NULL, NULL, 0, 0, "stericsson,db8500-thermal"),
|
||||
};
|
||||
|
||||
@@ -89,6 +89,11 @@ static const struct intel_lpss_platform_info apl_i2c_info = {
|
||||
.swnode = &apl_i2c_node,
|
||||
};
|
||||
|
||||
static const struct intel_lpss_platform_info cnl_i2c_info = {
|
||||
.clk_rate = 216000000,
|
||||
.swnode = &spt_i2c_node,
|
||||
};
|
||||
|
||||
static const struct acpi_device_id intel_lpss_acpi_ids[] = {
|
||||
/* SPT */
|
||||
{ "INT3440", (kernel_ulong_t)&spt_info },
|
||||
@@ -102,6 +107,19 @@ static const struct acpi_device_id intel_lpss_acpi_ids[] = {
|
||||
{ "INT3448", (kernel_ulong_t)&spt_uart_info },
|
||||
{ "INT3449", (kernel_ulong_t)&spt_uart_info },
|
||||
{ "INT344A", (kernel_ulong_t)&spt_uart_info },
|
||||
/* CNL */
|
||||
{ "INT34B0", (kernel_ulong_t)&spt_info },
|
||||
{ "INT34B1", (kernel_ulong_t)&spt_info },
|
||||
{ "INT34B2", (kernel_ulong_t)&cnl_i2c_info },
|
||||
{ "INT34B3", (kernel_ulong_t)&cnl_i2c_info },
|
||||
{ "INT34B4", (kernel_ulong_t)&cnl_i2c_info },
|
||||
{ "INT34B5", (kernel_ulong_t)&cnl_i2c_info },
|
||||
{ "INT34B6", (kernel_ulong_t)&cnl_i2c_info },
|
||||
{ "INT34B7", (kernel_ulong_t)&cnl_i2c_info },
|
||||
{ "INT34B8", (kernel_ulong_t)&spt_uart_info },
|
||||
{ "INT34B9", (kernel_ulong_t)&spt_uart_info },
|
||||
{ "INT34BA", (kernel_ulong_t)&spt_uart_info },
|
||||
{ "INT34BC", (kernel_ulong_t)&spt_info },
|
||||
/* BXT */
|
||||
{ "80860AAC", (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ "80860ABC", (kernel_ulong_t)&bxt_info },
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
|
||||
enum m10bmc_type {
|
||||
M10_N3000,
|
||||
M10_D5005
|
||||
M10_D5005,
|
||||
M10_N5010,
|
||||
};
|
||||
|
||||
static struct mfd_cell m10bmc_d5005_subdevs[] = {
|
||||
@@ -28,6 +29,10 @@ static struct mfd_cell m10bmc_pacn3000_subdevs[] = {
|
||||
{ .name = "n3000bmc-secure" },
|
||||
};
|
||||
|
||||
static struct mfd_cell m10bmc_n5010_subdevs[] = {
|
||||
{ .name = "n5010bmc-hwmon" },
|
||||
};
|
||||
|
||||
static const struct regmap_range m10bmc_regmap_range[] = {
|
||||
regmap_reg_range(M10BMC_LEGACY_BUILD_VER, M10BMC_LEGACY_BUILD_VER),
|
||||
regmap_reg_range(M10BMC_SYS_BASE, M10BMC_SYS_END),
|
||||
@@ -192,6 +197,10 @@ static int intel_m10_bmc_spi_probe(struct spi_device *spi)
|
||||
cells = m10bmc_d5005_subdevs;
|
||||
n_cell = ARRAY_SIZE(m10bmc_d5005_subdevs);
|
||||
break;
|
||||
case M10_N5010:
|
||||
cells = m10bmc_n5010_subdevs;
|
||||
n_cell = ARRAY_SIZE(m10bmc_n5010_subdevs);
|
||||
break;
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
@@ -207,6 +216,7 @@ static int intel_m10_bmc_spi_probe(struct spi_device *spi)
|
||||
static const struct spi_device_id m10bmc_spi_id[] = {
|
||||
{ "m10-n3000", M10_N3000 },
|
||||
{ "m10-d5005", M10_D5005 },
|
||||
{ "m10-n5010", M10_N5010 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, m10bmc_spi_id);
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/platform_data/gpio-dwapb.h>
|
||||
#include <linux/property.h>
|
||||
|
||||
/* PCI BAR for register base address */
|
||||
@@ -28,15 +27,6 @@
|
||||
#define MFD_ACPI_MATCH_GPIO 0ULL
|
||||
#define MFD_ACPI_MATCH_I2C 1ULL
|
||||
|
||||
/* The base GPIO number under GPIOLIB framework */
|
||||
#define INTEL_QUARK_MFD_GPIO_BASE 8
|
||||
|
||||
/* The default number of South-Cluster GPIO on Quark. */
|
||||
#define INTEL_QUARK_MFD_NGPIO 8
|
||||
|
||||
/* The DesignWare GPIO ports on Quark. */
|
||||
#define INTEL_QUARK_GPIO_NPORTS 1
|
||||
|
||||
#define INTEL_QUARK_IORES_MEM 0
|
||||
#define INTEL_QUARK_IORES_IRQ 1
|
||||
|
||||
@@ -111,12 +101,38 @@ static struct resource intel_quark_gpio_res[] = {
|
||||
[INTEL_QUARK_IORES_MEM] = {
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[INTEL_QUARK_IORES_IRQ] = {
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell_acpi_match intel_quark_acpi_match_gpio = {
|
||||
.adr = MFD_ACPI_MATCH_GPIO,
|
||||
};
|
||||
|
||||
static const struct software_node intel_quark_gpio_controller_node = {
|
||||
.name = "intel-quark-gpio-controller",
|
||||
};
|
||||
|
||||
static const struct property_entry intel_quark_gpio_portA_properties[] = {
|
||||
PROPERTY_ENTRY_U32("reg", 0),
|
||||
PROPERTY_ENTRY_U32("snps,nr-gpios", 8),
|
||||
PROPERTY_ENTRY_U32("gpio-base", 8),
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct software_node intel_quark_gpio_portA_node = {
|
||||
.name = "portA",
|
||||
.parent = &intel_quark_gpio_controller_node,
|
||||
.properties = intel_quark_gpio_portA_properties,
|
||||
};
|
||||
|
||||
static const struct software_node *intel_quark_gpio_node_group[] = {
|
||||
&intel_quark_gpio_controller_node,
|
||||
&intel_quark_gpio_portA_node,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct mfd_cell intel_quark_mfd_cells[] = {
|
||||
[MFD_I2C_BAR] = {
|
||||
.id = MFD_I2C_BAR,
|
||||
@@ -203,35 +219,19 @@ static int intel_quark_gpio_setup(struct pci_dev *pdev)
|
||||
{
|
||||
struct mfd_cell *cell = &intel_quark_mfd_cells[MFD_GPIO_BAR];
|
||||
struct resource *res = intel_quark_gpio_res;
|
||||
struct dwapb_platform_data *pdata;
|
||||
struct device *dev = &pdev->dev;
|
||||
int ret;
|
||||
|
||||
res[INTEL_QUARK_IORES_MEM].start = pci_resource_start(pdev, MFD_GPIO_BAR);
|
||||
res[INTEL_QUARK_IORES_MEM].end = pci_resource_end(pdev, MFD_GPIO_BAR);
|
||||
|
||||
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return -ENOMEM;
|
||||
res[INTEL_QUARK_IORES_IRQ].start = pci_irq_vector(pdev, 0);
|
||||
res[INTEL_QUARK_IORES_IRQ].end = pci_irq_vector(pdev, 0);
|
||||
|
||||
/* For intel quark x1000, it has only one port: portA */
|
||||
pdata->nports = INTEL_QUARK_GPIO_NPORTS;
|
||||
pdata->properties = devm_kcalloc(dev, pdata->nports,
|
||||
sizeof(*pdata->properties),
|
||||
GFP_KERNEL);
|
||||
if (!pdata->properties)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Set the properties for portA */
|
||||
pdata->properties->fwnode = NULL;
|
||||
pdata->properties->idx = 0;
|
||||
pdata->properties->ngpio = INTEL_QUARK_MFD_NGPIO;
|
||||
pdata->properties->gpio_base = INTEL_QUARK_MFD_GPIO_BASE;
|
||||
pdata->properties->irq[0] = pci_irq_vector(pdev, 0);
|
||||
pdata->properties->irq_shared = true;
|
||||
|
||||
cell->platform_data = pdata;
|
||||
cell->pdata_size = sizeof(*pdata);
|
||||
ret = software_node_register_node_group(intel_quark_gpio_node_group);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cell->swnode = &intel_quark_gpio_controller_node;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -274,10 +274,12 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev,
|
||||
ARRAY_SIZE(intel_quark_mfd_cells), NULL, 0,
|
||||
NULL);
|
||||
if (ret)
|
||||
goto err_free_irq_vectors;
|
||||
goto err_unregister_gpio_node_group;
|
||||
|
||||
return 0;
|
||||
|
||||
err_unregister_gpio_node_group:
|
||||
software_node_unregister_node_group(intel_quark_gpio_node_group);
|
||||
err_free_irq_vectors:
|
||||
pci_free_irq_vectors(pdev);
|
||||
err_unregister_i2c_clk:
|
||||
@@ -288,6 +290,7 @@ err_unregister_i2c_clk:
|
||||
static void intel_quark_mfd_remove(struct pci_dev *pdev)
|
||||
{
|
||||
mfd_remove_devices(&pdev->dev);
|
||||
software_node_unregister_node_group(intel_quark_gpio_node_group);
|
||||
pci_free_irq_vectors(pdev);
|
||||
intel_quark_unregister_i2c_clk(&pdev->dev);
|
||||
}
|
||||
|
||||
@@ -489,6 +489,7 @@ static struct lpc_ich_info lpc_chipset_info[] = {
|
||||
[LPC_DH89XXCC] = {
|
||||
.name = "DH89xxCC",
|
||||
.iTCO_version = 2,
|
||||
.gpio_version = ICH_V5_GPIO,
|
||||
},
|
||||
[LPC_PPT] = {
|
||||
.name = "Panther Point",
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#define SMBASE 0x40
|
||||
#define SMBUS_IO_SIZE 64
|
||||
|
||||
#define GPIOBASE 0x44
|
||||
#define GPIO_BASE 0x44
|
||||
#define GPIO_IO_SIZE 64
|
||||
#define GPIO_IO_SIZE_CENTERTON 128
|
||||
|
||||
@@ -145,7 +145,7 @@ static int lpc_sch_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
if (ret == 0)
|
||||
cells++;
|
||||
|
||||
ret = lpc_sch_populate_cell(dev, GPIOBASE, "sch_gpio",
|
||||
ret = lpc_sch_populate_cell(dev, GPIO_BASE, "sch_gpio",
|
||||
info->io_size_gpio,
|
||||
id->device, &lpc_sch_cells[cells]);
|
||||
if (ret < 0)
|
||||
|
||||
@@ -319,18 +319,18 @@ static const struct resource mt6360_regulator_resources[] = {
|
||||
DEFINE_RES_IRQ_NAMED(MT6360_BUCK2_OC_EVT, "buck2_oc_evt"),
|
||||
DEFINE_RES_IRQ_NAMED(MT6360_BUCK2_OV_EVT, "buck2_ov_evt"),
|
||||
DEFINE_RES_IRQ_NAMED(MT6360_BUCK2_UV_EVT, "buck2_uv_evt"),
|
||||
DEFINE_RES_IRQ_NAMED(MT6360_LDO6_OC_EVT, "ldo6_oc_evt"),
|
||||
DEFINE_RES_IRQ_NAMED(MT6360_LDO7_OC_EVT, "ldo7_oc_evt"),
|
||||
DEFINE_RES_IRQ_NAMED(MT6360_LDO6_PGB_EVT, "ldo6_pgb_evt"),
|
||||
DEFINE_RES_IRQ_NAMED(MT6360_LDO7_PGB_EVT, "ldo7_pgb_evt"),
|
||||
DEFINE_RES_IRQ_NAMED(MT6360_LDO1_OC_EVT, "ldo1_oc_evt"),
|
||||
DEFINE_RES_IRQ_NAMED(MT6360_LDO2_OC_EVT, "ldo2_oc_evt"),
|
||||
DEFINE_RES_IRQ_NAMED(MT6360_LDO3_OC_EVT, "ldo3_oc_evt"),
|
||||
DEFINE_RES_IRQ_NAMED(MT6360_LDO5_OC_EVT, "ldo5_oc_evt"),
|
||||
DEFINE_RES_IRQ_NAMED(MT6360_LDO6_OC_EVT, "ldo6_oc_evt"),
|
||||
DEFINE_RES_IRQ_NAMED(MT6360_LDO7_OC_EVT, "ldo7_oc_evt"),
|
||||
DEFINE_RES_IRQ_NAMED(MT6360_LDO1_PGB_EVT, "ldo1_pgb_evt"),
|
||||
DEFINE_RES_IRQ_NAMED(MT6360_LDO2_PGB_EVT, "ldo2_pgb_evt"),
|
||||
DEFINE_RES_IRQ_NAMED(MT6360_LDO3_PGB_EVT, "ldo3_pgb_evt"),
|
||||
DEFINE_RES_IRQ_NAMED(MT6360_LDO5_PGB_EVT, "ldo5_pgb_evt"),
|
||||
DEFINE_RES_IRQ_NAMED(MT6360_LDO6_PGB_EVT, "ldo6_pgb_evt"),
|
||||
DEFINE_RES_IRQ_NAMED(MT6360_LDO7_PGB_EVT, "ldo7_pgb_evt"),
|
||||
};
|
||||
|
||||
static const struct mfd_cell mt6360_devs[] = {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Renesas Synchronization Management Unit (SMU) devices.
|
||||
*
|
||||
* Copyright (C) 2021 Integrated Device Technology, Inc., a Renesas Company.
|
||||
*/
|
||||
|
||||
#ifndef __RSMU_MFD_H
|
||||
#define __RSMU_MFD_H
|
||||
|
||||
#include <linux/mfd/rsmu.h>
|
||||
|
||||
int rsmu_core_init(struct rsmu_ddata *rsmu);
|
||||
void rsmu_core_exit(struct rsmu_ddata *rsmu);
|
||||
|
||||
#endif /* __RSMU_MFD_H */
|
||||
@@ -0,0 +1,88 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Core driver for Renesas Synchronization Management Unit (SMU) devices.
|
||||
*
|
||||
* Copyright (C) 2021 Integrated Device Technology, Inc., a Renesas Company.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/rsmu.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "rsmu.h"
|
||||
|
||||
enum {
|
||||
RSMU_PHC = 0,
|
||||
RSMU_CDEV = 1,
|
||||
RSMU_N_DEVS = 2,
|
||||
};
|
||||
|
||||
static struct mfd_cell rsmu_cm_devs[] = {
|
||||
[RSMU_PHC] = {
|
||||
.name = "8a3400x-phc",
|
||||
},
|
||||
[RSMU_CDEV] = {
|
||||
.name = "8a3400x-cdev",
|
||||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell rsmu_sabre_devs[] = {
|
||||
[RSMU_PHC] = {
|
||||
.name = "82p33x1x-phc",
|
||||
},
|
||||
[RSMU_CDEV] = {
|
||||
.name = "82p33x1x-cdev",
|
||||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell rsmu_sl_devs[] = {
|
||||
[RSMU_PHC] = {
|
||||
.name = "8v19n85x-phc",
|
||||
},
|
||||
[RSMU_CDEV] = {
|
||||
.name = "8v19n85x-cdev",
|
||||
},
|
||||
};
|
||||
|
||||
int rsmu_core_init(struct rsmu_ddata *rsmu)
|
||||
{
|
||||
struct mfd_cell *cells;
|
||||
int ret;
|
||||
|
||||
switch (rsmu->type) {
|
||||
case RSMU_CM:
|
||||
cells = rsmu_cm_devs;
|
||||
break;
|
||||
case RSMU_SABRE:
|
||||
cells = rsmu_sabre_devs;
|
||||
break;
|
||||
case RSMU_SL:
|
||||
cells = rsmu_sl_devs;
|
||||
break;
|
||||
default:
|
||||
dev_err(rsmu->dev, "Unsupported RSMU device type: %d\n", rsmu->type);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mutex_init(&rsmu->lock);
|
||||
|
||||
ret = devm_mfd_add_devices(rsmu->dev, PLATFORM_DEVID_AUTO, cells,
|
||||
RSMU_N_DEVS, NULL, 0, NULL);
|
||||
if (ret < 0)
|
||||
dev_err(rsmu->dev, "Failed to register sub-devices: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void rsmu_core_exit(struct rsmu_ddata *rsmu)
|
||||
{
|
||||
mutex_destroy(&rsmu->lock);
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("Renesas SMU core driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,203 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* I2C driver for Renesas Synchronization Management Unit (SMU) devices.
|
||||
*
|
||||
* Copyright (C) 2021 Integrated Device Technology, Inc., a Renesas Company.
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/rsmu.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#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.
|
||||
*/
|
||||
#define RSMU_CM_PAGE_ADDR 0xFD
|
||||
#define RSMU_CM_PAGE_WINDOW 256
|
||||
|
||||
/*
|
||||
* 15-bit register address: the lower 7 bits of the register address come
|
||||
* from the offset addr byte and the upper 8 bits come from the page register.
|
||||
*/
|
||||
#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,
|
||||
.range_max = 0x400,
|
||||
.selector_reg = RSMU_SABRE_PAGE_ADDR,
|
||||
.selector_mask = 0xFF,
|
||||
.selector_shift = 0,
|
||||
.window_start = 0,
|
||||
.window_len = RSMU_SABRE_PAGE_WINDOW,
|
||||
}
|
||||
};
|
||||
|
||||
static bool rsmu_cm_volatile_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case RSMU_CM_PAGE_ADDR:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool rsmu_sabre_volatile_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case RSMU_SABRE_PAGE_ADDR:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct regmap_config rsmu_cm_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.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,
|
||||
};
|
||||
|
||||
static const struct regmap_config rsmu_sabre_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = 0x400,
|
||||
.ranges = rsmu_sabre_range_cfg,
|
||||
.num_ranges = ARRAY_SIZE(rsmu_sabre_range_cfg),
|
||||
.volatile_reg = rsmu_sabre_volatile_reg,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
.can_multi_write = true,
|
||||
};
|
||||
|
||||
static const struct regmap_config rsmu_sl_regmap_config = {
|
||||
.reg_bits = 16,
|
||||
.val_bits = 8,
|
||||
.reg_format_endian = REGMAP_ENDIAN_BIG,
|
||||
.max_register = 0x339,
|
||||
.cache_type = REGCACHE_NONE,
|
||||
.can_multi_write = true,
|
||||
};
|
||||
|
||||
static int rsmu_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
const struct regmap_config *cfg;
|
||||
struct rsmu_ddata *rsmu;
|
||||
int ret;
|
||||
|
||||
rsmu = devm_kzalloc(&client->dev, sizeof(*rsmu), GFP_KERNEL);
|
||||
if (!rsmu)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, rsmu);
|
||||
|
||||
rsmu->dev = &client->dev;
|
||||
rsmu->type = (enum rsmu_type)id->driver_data;
|
||||
|
||||
switch (rsmu->type) {
|
||||
case RSMU_CM:
|
||||
cfg = &rsmu_cm_regmap_config;
|
||||
break;
|
||||
case RSMU_SABRE:
|
||||
cfg = &rsmu_sabre_regmap_config;
|
||||
break;
|
||||
case RSMU_SL:
|
||||
cfg = &rsmu_sl_regmap_config;
|
||||
break;
|
||||
default:
|
||||
dev_err(rsmu->dev, "Unsupported RSMU device type: %d\n", rsmu->type);
|
||||
return -ENODEV;
|
||||
}
|
||||
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);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return rsmu_core_init(rsmu);
|
||||
}
|
||||
|
||||
static int rsmu_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct rsmu_ddata *rsmu = i2c_get_clientdata(client);
|
||||
|
||||
rsmu_core_exit(rsmu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id rsmu_i2c_id[] = {
|
||||
{ "8a34000", RSMU_CM },
|
||||
{ "8a34001", RSMU_CM },
|
||||
{ "82p33810", RSMU_SABRE },
|
||||
{ "82p33811", RSMU_SABRE },
|
||||
{ "8v19n850", RSMU_SL },
|
||||
{ "8v19n851", RSMU_SL },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rsmu_i2c_id);
|
||||
|
||||
static const struct of_device_id rsmu_i2c_of_match[] = {
|
||||
{ .compatible = "idt,8a34000", .data = (void *)RSMU_CM },
|
||||
{ .compatible = "idt,8a34001", .data = (void *)RSMU_CM },
|
||||
{ .compatible = "idt,82p33810", .data = (void *)RSMU_SABRE },
|
||||
{ .compatible = "idt,82p33811", .data = (void *)RSMU_SABRE },
|
||||
{ .compatible = "idt,8v19n850", .data = (void *)RSMU_SL },
|
||||
{ .compatible = "idt,8v19n851", .data = (void *)RSMU_SL },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rsmu_i2c_of_match);
|
||||
|
||||
static struct i2c_driver rsmu_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "rsmu-i2c",
|
||||
.of_match_table = of_match_ptr(rsmu_i2c_of_match),
|
||||
},
|
||||
.probe = rsmu_i2c_probe,
|
||||
.remove = rsmu_i2c_remove,
|
||||
.id_table = rsmu_i2c_id,
|
||||
};
|
||||
|
||||
static int __init rsmu_i2c_init(void)
|
||||
{
|
||||
return i2c_add_driver(&rsmu_i2c_driver);
|
||||
}
|
||||
subsys_initcall(rsmu_i2c_init);
|
||||
|
||||
static void __exit rsmu_i2c_exit(void)
|
||||
{
|
||||
i2c_del_driver(&rsmu_i2c_driver);
|
||||
}
|
||||
module_exit(rsmu_i2c_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Renesas SMU I2C driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,273 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* SPI driver for Renesas Synchronization Management Unit (SMU) devices.
|
||||
*
|
||||
* Copyright (C) 2021 Integrated Device Technology, Inc., a Renesas Company.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/rsmu.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include "rsmu.h"
|
||||
|
||||
#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
|
||||
|
||||
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};
|
||||
int ret;
|
||||
|
||||
cmd[0] = reg | 0x80;
|
||||
xfer.rx_buf = rsp;
|
||||
xfer.len = bytes + 1;
|
||||
xfer.tx_buf = cmd;
|
||||
xfer.bits_per_word = client->bits_per_word;
|
||||
xfer.speed_hz = client->max_speed_hz;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfer, &msg);
|
||||
|
||||
/*
|
||||
* 4-wire SPI is a shift register, so for every byte you send,
|
||||
* you get one back at the same time. Example read from 0xC024,
|
||||
* which has value of 0x2D
|
||||
*
|
||||
* MOSI:
|
||||
* 7C 00 C0 #Set page register
|
||||
* A4 00 #MSB is set, so this is read command
|
||||
* MISO:
|
||||
* XX 2D #XX is a dummy byte from sending A4 and we
|
||||
* need to throw it away
|
||||
*/
|
||||
ret = spi_sync(client, &msg);
|
||||
if (ret >= 0)
|
||||
memcpy(buf, &rsp[1], xfer.len-1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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};
|
||||
|
||||
cmd[0] = reg;
|
||||
memcpy(&cmd[1], buf, bytes);
|
||||
|
||||
xfer.len = bytes + 1;
|
||||
xfer.tx_buf = cmd;
|
||||
xfer.bits_per_word = client->bits_per_word;
|
||||
xfer.speed_hz = client->max_speed_hz;
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfer, &msg);
|
||||
|
||||
return spi_sync(client, &msg);
|
||||
}
|
||||
|
||||
/*
|
||||
* 1-byte (1B) offset addressing:
|
||||
* 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)
|
||||
{
|
||||
u8 page_reg;
|
||||
u8 buf[2];
|
||||
u16 bytes;
|
||||
u16 page;
|
||||
int err;
|
||||
|
||||
switch (rsmu->type) {
|
||||
case RSMU_CM:
|
||||
page_reg = RSMU_CM_PAGE_ADDR;
|
||||
page = reg & RSMU_HIGHER_ADDR_MASK;
|
||||
buf[0] = (u8)(page & 0xff);
|
||||
buf[1] = (u8)((page >> 8) & 0xff);
|
||||
bytes = 2;
|
||||
break;
|
||||
case RSMU_SABRE:
|
||||
page_reg = RSMU_SABRE_PAGE_ADDR;
|
||||
page = reg >> RSMU_HIGHER_ADDR_SHIFT;
|
||||
buf[0] = (u8)(page & 0xff);
|
||||
bytes = 1;
|
||||
break;
|
||||
default:
|
||||
dev_err(rsmu->dev, "Unsupported RSMU device type: %d\n", rsmu->type);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Simply return if we are on the same page */
|
||||
if (rsmu->page == page)
|
||||
return 0;
|
||||
|
||||
err = rsmu_write_device(rsmu, page_reg, buf, bytes);
|
||||
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 = spi_get_drvdata((struct spi_device *)context);
|
||||
u8 addr = (u8)(reg & RSMU_LOWER_ADDR_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 = spi_get_drvdata((struct spi_device *)context);
|
||||
u8 addr = (u8)(reg & RSMU_LOWER_ADDR_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 = 16,
|
||||
.val_bits = 8,
|
||||
.max_register = 0xD000,
|
||||
.reg_read = rsmu_reg_read,
|
||||
.reg_write = rsmu_reg_write,
|
||||
.cache_type = REGCACHE_NONE,
|
||||
};
|
||||
|
||||
static const struct regmap_config rsmu_sabre_regmap_config = {
|
||||
.reg_bits = 16,
|
||||
.val_bits = 8,
|
||||
.max_register = 0x400,
|
||||
.reg_read = rsmu_reg_read,
|
||||
.reg_write = rsmu_reg_write,
|
||||
.cache_type = REGCACHE_NONE,
|
||||
};
|
||||
|
||||
static int rsmu_spi_probe(struct spi_device *client)
|
||||
{
|
||||
const struct spi_device_id *id = spi_get_device_id(client);
|
||||
const struct regmap_config *cfg;
|
||||
struct rsmu_ddata *rsmu;
|
||||
int ret;
|
||||
|
||||
rsmu = devm_kzalloc(&client->dev, sizeof(*rsmu), GFP_KERNEL);
|
||||
if (!rsmu)
|
||||
return -ENOMEM;
|
||||
|
||||
spi_set_drvdata(client, rsmu);
|
||||
|
||||
rsmu->dev = &client->dev;
|
||||
rsmu->type = (enum rsmu_type)id->driver_data;
|
||||
|
||||
/* Initialize regmap */
|
||||
switch (rsmu->type) {
|
||||
case RSMU_CM:
|
||||
cfg = &rsmu_cm_regmap_config;
|
||||
break;
|
||||
case RSMU_SABRE:
|
||||
cfg = &rsmu_sabre_regmap_config;
|
||||
break;
|
||||
default:
|
||||
dev_err(rsmu->dev, "Unsupported RSMU device type: %d\n", rsmu->type);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rsmu->regmap = devm_regmap_init(&client->dev, NULL, client, cfg);
|
||||
if (IS_ERR(rsmu->regmap)) {
|
||||
ret = PTR_ERR(rsmu->regmap);
|
||||
dev_err(rsmu->dev, "Failed to allocate register map: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return rsmu_core_init(rsmu);
|
||||
}
|
||||
|
||||
static int rsmu_spi_remove(struct spi_device *client)
|
||||
{
|
||||
struct rsmu_ddata *rsmu = spi_get_drvdata(client);
|
||||
|
||||
rsmu_core_exit(rsmu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct spi_device_id rsmu_spi_id[] = {
|
||||
{ "8a34000", RSMU_CM },
|
||||
{ "8a34001", RSMU_CM },
|
||||
{ "82p33810", RSMU_SABRE },
|
||||
{ "82p33811", RSMU_SABRE },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, rsmu_spi_id);
|
||||
|
||||
static const struct of_device_id rsmu_spi_of_match[] = {
|
||||
{ .compatible = "idt,8a34000", .data = (void *)RSMU_CM },
|
||||
{ .compatible = "idt,8a34001", .data = (void *)RSMU_CM },
|
||||
{ .compatible = "idt,82p33810", .data = (void *)RSMU_SABRE },
|
||||
{ .compatible = "idt,82p33811", .data = (void *)RSMU_SABRE },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rsmu_spi_of_match);
|
||||
|
||||
static struct spi_driver rsmu_spi_driver = {
|
||||
.driver = {
|
||||
.name = "rsmu-spi",
|
||||
.of_match_table = of_match_ptr(rsmu_spi_of_match),
|
||||
},
|
||||
.probe = rsmu_spi_probe,
|
||||
.remove = rsmu_spi_remove,
|
||||
.id_table = rsmu_spi_id,
|
||||
};
|
||||
|
||||
static int __init rsmu_spi_init(void)
|
||||
{
|
||||
return spi_register_driver(&rsmu_spi_driver);
|
||||
}
|
||||
subsys_initcall(rsmu_spi_init);
|
||||
|
||||
static void __exit rsmu_spi_exit(void)
|
||||
{
|
||||
spi_unregister_driver(&rsmu_spi_driver);
|
||||
}
|
||||
module_exit(rsmu_spi_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Renesas SMU SPI driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -2,39 +2,64 @@
|
||||
/*
|
||||
* Simple MFD - I2C
|
||||
*
|
||||
* Author(s):
|
||||
* Michael Walle <michael@walle.cc>
|
||||
* Lee Jones <lee.jones@linaro.org>
|
||||
*
|
||||
* This driver creates a single register map with the intention for it to be
|
||||
* shared by all sub-devices. Children can use their parent's device structure
|
||||
* (dev.parent) in order to reference it.
|
||||
*
|
||||
* Once the register map has been successfully initialised, any sub-devices
|
||||
* represented by child nodes in Device Tree will be subsequently registered.
|
||||
* represented by child nodes in Device Tree or via the MFD cells in this file
|
||||
* will be subsequently registered.
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
static const struct regmap_config simple_regmap_config = {
|
||||
#include "simple-mfd-i2c.h"
|
||||
|
||||
static const struct regmap_config regmap_config_8r_8v = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
};
|
||||
|
||||
static int simple_mfd_i2c_probe(struct i2c_client *i2c)
|
||||
{
|
||||
const struct regmap_config *config;
|
||||
const struct simple_mfd_data *simple_mfd_data;
|
||||
const struct regmap_config *regmap_config;
|
||||
struct regmap *regmap;
|
||||
int ret;
|
||||
|
||||
config = device_get_match_data(&i2c->dev);
|
||||
if (!config)
|
||||
config = &simple_regmap_config;
|
||||
simple_mfd_data = device_get_match_data(&i2c->dev);
|
||||
|
||||
regmap = devm_regmap_init_i2c(i2c, config);
|
||||
/* If no regmap_config is specified, use the default 8reg and 8val bits */
|
||||
if (!simple_mfd_data || !simple_mfd_data->regmap_config)
|
||||
regmap_config = ®map_config_8r_8v;
|
||||
else
|
||||
regmap_config = simple_mfd_data->regmap_config;
|
||||
|
||||
regmap = devm_regmap_init_i2c(i2c, regmap_config);
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
return devm_of_platform_populate(&i2c->dev);
|
||||
/* If no MFD cells are spedified, use register the DT child nodes instead */
|
||||
if (!simple_mfd_data || !simple_mfd_data->mfd_cell)
|
||||
return devm_of_platform_populate(&i2c->dev);
|
||||
|
||||
ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO,
|
||||
simple_mfd_data->mfd_cell,
|
||||
simple_mfd_data->mfd_cell_size,
|
||||
NULL, 0, NULL);
|
||||
if (ret)
|
||||
dev_err(&i2c->dev, "Failed to add child devices\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id simple_mfd_i2c_of_match[] = {
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Simple MFD - I2C
|
||||
*
|
||||
* Author: Lee Jones <lee.jones@linaro.org>
|
||||
*
|
||||
* This driver creates a single register map with the intention for it to be
|
||||
* shared by all sub-devices. Children can use their parent's device structure
|
||||
* (dev.parent) in order to reference it.
|
||||
*
|
||||
* This driver creates a single register map with the intention for it to be
|
||||
* shared by all sub-devices. Children can use their parent's device structure
|
||||
* (dev.parent) in order to reference it.
|
||||
*
|
||||
* Once the register map has been successfully initialised, any sub-devices
|
||||
* represented by child nodes in Device Tree or via the MFD cells in the
|
||||
* associated C file will be subsequently registered.
|
||||
*/
|
||||
|
||||
#ifndef __MFD_SIMPLE_MFD_I2C_H
|
||||
#define __MFD_SIMPLE_MFD_I2C_H
|
||||
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
struct simple_mfd_data {
|
||||
const struct regmap_config *regmap_config;
|
||||
const struct mfd_cell *mfd_cell;
|
||||
size_t mfd_cell_size;
|
||||
};
|
||||
|
||||
#endif /* __MFD_SIMPLE_MFD_I2C_H */
|
||||
+2
-2
@@ -1095,7 +1095,7 @@ static irqreturn_t stmpe_irq(int irq, void *data)
|
||||
|
||||
if (variant->id_val == STMPE801_ID ||
|
||||
variant->id_val == STMPE1600_ID) {
|
||||
int base = irq_create_mapping(stmpe->domain, 0);
|
||||
int base = irq_find_mapping(stmpe->domain, 0);
|
||||
|
||||
handle_nested_irq(base);
|
||||
return IRQ_HANDLED;
|
||||
@@ -1123,7 +1123,7 @@ static irqreturn_t stmpe_irq(int irq, void *data)
|
||||
while (status) {
|
||||
int bit = __ffs(status);
|
||||
int line = bank * 8 + bit;
|
||||
int nestedirq = irq_create_mapping(stmpe->domain, line);
|
||||
int nestedirq = irq_find_mapping(stmpe->domain, line);
|
||||
|
||||
handle_nested_irq(nestedirq);
|
||||
status &= ~(1 << bit);
|
||||
|
||||
@@ -60,7 +60,7 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_clk)
|
||||
goto err_map;
|
||||
}
|
||||
|
||||
base = ioremap(res.start, resource_size(&res));
|
||||
base = of_iomap(np, 0);
|
||||
if (!base) {
|
||||
ret = -ENOMEM;
|
||||
goto err_map;
|
||||
|
||||
@@ -187,7 +187,7 @@ again:
|
||||
|
||||
while (status) {
|
||||
int bit = __ffs(status);
|
||||
int virq = irq_create_mapping(tc3589x->domain, bit);
|
||||
int virq = irq_find_mapping(tc3589x->domain, bit);
|
||||
|
||||
handle_nested_irq(virq);
|
||||
status &= ~(1 << bit);
|
||||
|
||||
@@ -175,10 +175,9 @@ static int ti_tscadc_probe(struct platform_device *pdev)
|
||||
tscadc->dev = &pdev->dev;
|
||||
|
||||
err = platform_get_irq(pdev, 0);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "no irq ID is specified.\n");
|
||||
if (err < 0)
|
||||
goto ret;
|
||||
} else
|
||||
else
|
||||
tscadc->irq = err;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
||||
+12
-10
@@ -24,6 +24,7 @@
|
||||
static const struct mfd_cell tps65086_cells[] = {
|
||||
{ .name = "tps65086-regulator", },
|
||||
{ .name = "tps65086-gpio", },
|
||||
{ .name = "tps65086-reset", },
|
||||
};
|
||||
|
||||
static const struct regmap_range tps65086_yes_ranges[] = {
|
||||
@@ -100,29 +101,30 @@ static int tps65086_probe(struct i2c_client *client,
|
||||
(char)((version & TPS65086_DEVICEID_OTP_MASK) >> 4) + 'A',
|
||||
(version & TPS65086_DEVICEID_REV_MASK) >> 6);
|
||||
|
||||
ret = regmap_add_irq_chip(tps->regmap, tps->irq, IRQF_ONESHOT, 0,
|
||||
&tps65086_irq_chip, &tps->irq_data);
|
||||
if (ret) {
|
||||
dev_err(tps->dev, "Failed to register IRQ chip\n");
|
||||
return ret;
|
||||
if (tps->irq > 0) {
|
||||
ret = regmap_add_irq_chip(tps->regmap, tps->irq, IRQF_ONESHOT, 0,
|
||||
&tps65086_irq_chip, &tps->irq_data);
|
||||
if (ret) {
|
||||
dev_err(tps->dev, "Failed to register IRQ chip\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = mfd_add_devices(tps->dev, PLATFORM_DEVID_AUTO, tps65086_cells,
|
||||
ARRAY_SIZE(tps65086_cells), NULL, 0,
|
||||
regmap_irq_get_domain(tps->irq_data));
|
||||
if (ret) {
|
||||
if (ret && tps->irq > 0)
|
||||
regmap_del_irq_chip(tps->irq, tps->irq_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tps65086_remove(struct i2c_client *client)
|
||||
{
|
||||
struct tps65086 *tps = i2c_get_clientdata(client);
|
||||
|
||||
regmap_del_irq_chip(tps->irq, tps->irq_data);
|
||||
if (tps->irq > 0)
|
||||
regmap_del_irq_chip(tps->irq, tps->irq_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+38
-10
@@ -35,7 +35,11 @@
|
||||
#define TQMX86_REG_BOARD_ID_E39x 7
|
||||
#define TQMX86_REG_BOARD_ID_70EB 8
|
||||
#define TQMX86_REG_BOARD_ID_80UC 9
|
||||
#define TQMX86_REG_BOARD_ID_90UC 10
|
||||
#define TQMX86_REG_BOARD_ID_110EB 11
|
||||
#define TQMX86_REG_BOARD_ID_E40M 12
|
||||
#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_IO_EXT_INT_NONE 0
|
||||
@@ -77,7 +81,7 @@ static struct i2c_board_info tqmx86_i2c_devices[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct ocores_i2c_platform_data ocores_platfom_data = {
|
||||
static struct ocores_i2c_platform_data ocores_platform_data = {
|
||||
.num_devices = ARRAY_SIZE(tqmx86_i2c_devices),
|
||||
.devices = tqmx86_i2c_devices,
|
||||
};
|
||||
@@ -85,8 +89,8 @@ static struct ocores_i2c_platform_data ocores_platfom_data = {
|
||||
static const struct mfd_cell tqmx86_i2c_soft_dev[] = {
|
||||
{
|
||||
.name = "ocores-i2c",
|
||||
.platform_data = &ocores_platfom_data,
|
||||
.pdata_size = sizeof(ocores_platfom_data),
|
||||
.platform_data = &ocores_platform_data,
|
||||
.pdata_size = sizeof(ocores_platform_data),
|
||||
.resources = tqmx_i2c_soft_resources,
|
||||
.num_resources = ARRAY_SIZE(tqmx_i2c_soft_resources),
|
||||
},
|
||||
@@ -128,21 +132,33 @@ static const char *tqmx86_board_id_to_name(u8 board_id)
|
||||
return "TQMx70EB";
|
||||
case TQMX86_REG_BOARD_ID_80UC:
|
||||
return "TQMx80UC";
|
||||
case TQMX86_REG_BOARD_ID_90UC:
|
||||
return "TQMx90UC";
|
||||
case TQMX86_REG_BOARD_ID_110EB:
|
||||
return "TQMx110EB";
|
||||
case TQMX86_REG_BOARD_ID_E40M:
|
||||
return "TQMxE40M";
|
||||
case TQMX86_REG_BOARD_ID_E40S:
|
||||
return "TQMxE40S";
|
||||
case TQMX86_REG_BOARD_ID_E40C1:
|
||||
return "TQMxE40C1";
|
||||
case TQMX86_REG_BOARD_ID_E40C2:
|
||||
return "TQMxE40C2";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static int tqmx86_board_id_to_clk_rate(u8 board_id)
|
||||
static int tqmx86_board_id_to_clk_rate(struct device *dev, u8 board_id)
|
||||
{
|
||||
switch (board_id) {
|
||||
case TQMX86_REG_BOARD_ID_50UC:
|
||||
case TQMX86_REG_BOARD_ID_60EB:
|
||||
case TQMX86_REG_BOARD_ID_70EB:
|
||||
case TQMX86_REG_BOARD_ID_80UC:
|
||||
case TQMX86_REG_BOARD_ID_90UC:
|
||||
case TQMX86_REG_BOARD_ID_110EB:
|
||||
case TQMX86_REG_BOARD_ID_E40M:
|
||||
case TQMX86_REG_BOARD_ID_E40S:
|
||||
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:
|
||||
@@ -152,7 +168,9 @@ static int tqmx86_board_id_to_clk_rate(u8 board_id)
|
||||
case TQMX86_REG_BOARD_ID_E38C:
|
||||
return 33000;
|
||||
default:
|
||||
return 0;
|
||||
dev_warn(dev, "unknown board %d, assuming 24MHz LPC clock\n",
|
||||
board_id);
|
||||
return 24000;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,9 +227,11 @@ static int tqmx86_probe(struct platform_device *pdev)
|
||||
|
||||
/* Assumes the IRQ resource is first. */
|
||||
tqmx_gpio_resources[0].start = gpio_irq;
|
||||
} else {
|
||||
tqmx_gpio_resources[0].flags = 0;
|
||||
}
|
||||
|
||||
ocores_platfom_data.clock_khz = tqmx86_board_id_to_clk_rate(board_id);
|
||||
ocores_platform_data.clock_khz = tqmx86_board_id_to_clk_rate(dev, board_id);
|
||||
|
||||
if (i2c_det == TQMX86_REG_I2C_DETECT_SOFT) {
|
||||
err = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
|
||||
@@ -253,6 +273,14 @@ static const struct dmi_system_id tqmx86_dmi_table[] __initconst = {
|
||||
},
|
||||
.callback = tqmx86_create_platform_device,
|
||||
},
|
||||
{
|
||||
.ident = "TQMX86",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TQ-Systems"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "TQMx"),
|
||||
},
|
||||
.callback = tqmx86_create_platform_device,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(dmi, tqmx86_dmi_table);
|
||||
|
||||
@@ -154,7 +154,7 @@ static irqreturn_t wm8994_edge_irq(int irq, void *data)
|
||||
struct wm8994 *wm8994 = data;
|
||||
|
||||
while (gpio_get_value_cansleep(wm8994->pdata.irq_gpio))
|
||||
handle_nested_irq(irq_create_mapping(wm8994->edge_irq, 0));
|
||||
handle_nested_irq(irq_find_mapping(wm8994->edge_irq, 0));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#define KTD253_T_LOW_NS (200 + 10) /* Additional 10ns as safety factor */
|
||||
#define KTD253_T_HIGH_NS (200 + 10) /* Additional 10ns as safety factor */
|
||||
#define KTD253_T_OFF_CRIT_NS 100000 /* 100 us, now it doesn't look good */
|
||||
#define KTD253_T_OFF_MS 3
|
||||
|
||||
struct ktd253_backlight {
|
||||
@@ -34,13 +35,50 @@ struct ktd253_backlight {
|
||||
u16 ratio;
|
||||
};
|
||||
|
||||
static void ktd253_backlight_set_max_ratio(struct ktd253_backlight *ktd253)
|
||||
{
|
||||
gpiod_set_value_cansleep(ktd253->gpiod, 1);
|
||||
ndelay(KTD253_T_HIGH_NS);
|
||||
/* We always fall back to this when we power on */
|
||||
}
|
||||
|
||||
static int ktd253_backlight_stepdown(struct ktd253_backlight *ktd253)
|
||||
{
|
||||
/*
|
||||
* These GPIO operations absolutely can NOT sleep so no _cansleep
|
||||
* suffixes, and no using GPIO expanders on slow buses for this!
|
||||
*
|
||||
* The maximum number of cycles of the loop is 32 so the time taken
|
||||
* should nominally be:
|
||||
* (T_LOW_NS + T_HIGH_NS + loop_time) * 32
|
||||
*
|
||||
* Architectures do not always support ndelay() and we will get a few us
|
||||
* instead. If we get to a critical time limit an interrupt has likely
|
||||
* occured in the low part of the loop and we need to restart from the
|
||||
* top so we have the backlight in a known state.
|
||||
*/
|
||||
u64 ns;
|
||||
|
||||
ns = ktime_get_ns();
|
||||
gpiod_set_value(ktd253->gpiod, 0);
|
||||
ndelay(KTD253_T_LOW_NS);
|
||||
gpiod_set_value(ktd253->gpiod, 1);
|
||||
ns = ktime_get_ns() - ns;
|
||||
if (ns >= KTD253_T_OFF_CRIT_NS) {
|
||||
dev_err(ktd253->dev, "PCM on backlight took too long (%llu ns)\n", ns);
|
||||
return -EAGAIN;
|
||||
}
|
||||
ndelay(KTD253_T_HIGH_NS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ktd253_backlight_update_status(struct backlight_device *bl)
|
||||
{
|
||||
struct ktd253_backlight *ktd253 = bl_get_data(bl);
|
||||
int brightness = backlight_get_brightness(bl);
|
||||
u16 target_ratio;
|
||||
u16 current_ratio = ktd253->ratio;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
dev_dbg(ktd253->dev, "new brightness/ratio: %d/32\n", brightness);
|
||||
|
||||
@@ -62,37 +100,34 @@ static int ktd253_backlight_update_status(struct backlight_device *bl)
|
||||
}
|
||||
|
||||
if (current_ratio == 0) {
|
||||
gpiod_set_value_cansleep(ktd253->gpiod, 1);
|
||||
ndelay(KTD253_T_HIGH_NS);
|
||||
/* We always fall back to this when we power on */
|
||||
ktd253_backlight_set_max_ratio(ktd253);
|
||||
current_ratio = KTD253_MAX_RATIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING:
|
||||
* The loop to set the correct current level is performed
|
||||
* with interrupts disabled as it is timing critical.
|
||||
* The maximum number of cycles of the loop is 32
|
||||
* so the time taken will be (T_LOW_NS + T_HIGH_NS + loop_time) * 32,
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
while (current_ratio != target_ratio) {
|
||||
/*
|
||||
* These GPIO operations absolutely can NOT sleep so no
|
||||
* _cansleep suffixes, and no using GPIO expanders on
|
||||
* slow buses for this!
|
||||
*/
|
||||
gpiod_set_value(ktd253->gpiod, 0);
|
||||
ndelay(KTD253_T_LOW_NS);
|
||||
gpiod_set_value(ktd253->gpiod, 1);
|
||||
ndelay(KTD253_T_HIGH_NS);
|
||||
/* After 1/32 we loop back to 32/32 */
|
||||
if (current_ratio == KTD253_MIN_RATIO)
|
||||
ret = ktd253_backlight_stepdown(ktd253);
|
||||
if (ret == -EAGAIN) {
|
||||
/*
|
||||
* Something disturbed the backlight setting code when
|
||||
* running so we need to bring the PWM back to a known
|
||||
* state. This shouldn't happen too much.
|
||||
*/
|
||||
gpiod_set_value_cansleep(ktd253->gpiod, 0);
|
||||
msleep(KTD253_T_OFF_MS);
|
||||
ktd253_backlight_set_max_ratio(ktd253);
|
||||
current_ratio = KTD253_MAX_RATIO;
|
||||
else
|
||||
} else if (current_ratio == KTD253_MIN_RATIO) {
|
||||
/* After 1/32 we loop back to 32/32 */
|
||||
current_ratio = KTD253_MAX_RATIO;
|
||||
} else {
|
||||
current_ratio--;
|
||||
}
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
ktd253->ratio = current_ratio;
|
||||
|
||||
dev_dbg(ktd253->dev, "new ratio set to %d/32\n", target_ratio);
|
||||
|
||||
@@ -409,6 +409,33 @@ static bool pwm_backlight_is_linear(struct platform_pwm_backlight_data *data)
|
||||
static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb)
|
||||
{
|
||||
struct device_node *node = pb->dev->of_node;
|
||||
bool active = true;
|
||||
|
||||
/*
|
||||
* If the enable GPIO is present, observable (either as input
|
||||
* or output) and off then the backlight is not currently active.
|
||||
* */
|
||||
if (pb->enable_gpio && gpiod_get_value_cansleep(pb->enable_gpio) == 0)
|
||||
active = false;
|
||||
|
||||
if (!regulator_is_enabled(pb->power_supply))
|
||||
active = false;
|
||||
|
||||
if (!pwm_is_enabled(pb->pwm))
|
||||
active = false;
|
||||
|
||||
/*
|
||||
* Synchronize the enable_gpio with the observed state of the
|
||||
* hardware.
|
||||
*/
|
||||
if (pb->enable_gpio)
|
||||
gpiod_direction_output(pb->enable_gpio, active);
|
||||
|
||||
/*
|
||||
* Do not change pb->enabled here! pb->enabled essentially
|
||||
* tells us if we own one of the regulator's use counts and
|
||||
* right now we do not.
|
||||
*/
|
||||
|
||||
/* Not booted with device tree or no phandle link to the node */
|
||||
if (!node || !node->phandle)
|
||||
@@ -420,20 +447,7 @@ static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb)
|
||||
* assume that another driver will enable the backlight at the
|
||||
* appropriate time. Therefore, if it is disabled, keep it so.
|
||||
*/
|
||||
|
||||
/* if the enable GPIO is disabled, do not enable the backlight */
|
||||
if (pb->enable_gpio && gpiod_get_value_cansleep(pb->enable_gpio) == 0)
|
||||
return FB_BLANK_POWERDOWN;
|
||||
|
||||
/* The regulator is disabled, do not enable the backlight */
|
||||
if (!regulator_is_enabled(pb->power_supply))
|
||||
return FB_BLANK_POWERDOWN;
|
||||
|
||||
/* The PWM is disabled, keep it like this */
|
||||
if (!pwm_is_enabled(pb->pwm))
|
||||
return FB_BLANK_POWERDOWN;
|
||||
|
||||
return FB_BLANK_UNBLANK;
|
||||
return active ? FB_BLANK_UNBLANK: FB_BLANK_POWERDOWN;
|
||||
}
|
||||
|
||||
static int pwm_backlight_probe(struct platform_device *pdev)
|
||||
@@ -486,18 +500,6 @@ static int pwm_backlight_probe(struct platform_device *pdev)
|
||||
goto err_alloc;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the GPIO is not known to be already configured as output, that
|
||||
* is, if gpiod_get_direction returns either 1 or -EINVAL, change the
|
||||
* direction to output and set the GPIO as active.
|
||||
* Do not force the GPIO to active when it was already output as it
|
||||
* could cause backlight flickering or we would enable the backlight too
|
||||
* early. Leave the decision of the initial backlight state for later.
|
||||
*/
|
||||
if (pb->enable_gpio &&
|
||||
gpiod_get_direction(pb->enable_gpio) != 0)
|
||||
gpiod_direction_output(pb->enable_gpio, 1);
|
||||
|
||||
pb->power_supply = devm_regulator_get(&pdev->dev, "power");
|
||||
if (IS_ERR(pb->power_supply)) {
|
||||
ret = PTR_ERR(pb->power_supply);
|
||||
|
||||
@@ -609,7 +609,7 @@ struct gpio_desc *devm_fwnode_get_gpiod_from_child(struct device *dev,
|
||||
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_OF_GPIO)
|
||||
struct device_node;
|
||||
|
||||
struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
|
||||
struct gpio_desc *gpiod_get_from_of_node(const struct device_node *node,
|
||||
const char *propname, int index,
|
||||
enum gpiod_flags dflags,
|
||||
const char *label);
|
||||
@@ -619,7 +619,7 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
|
||||
struct device_node;
|
||||
|
||||
static inline
|
||||
struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
|
||||
struct gpio_desc *gpiod_get_from_of_node(const struct device_node *node,
|
||||
const char *propname, int index,
|
||||
enum gpiod_flags dflags,
|
||||
const char *label)
|
||||
@@ -633,7 +633,7 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
|
||||
struct device_node;
|
||||
|
||||
struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
|
||||
struct device_node *node,
|
||||
const struct device_node *node,
|
||||
const char *propname, int index,
|
||||
enum gpiod_flags dflags,
|
||||
const char *label);
|
||||
@@ -644,7 +644,7 @@ struct device_node;
|
||||
|
||||
static inline
|
||||
struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
|
||||
struct device_node *node,
|
||||
const struct device_node *node,
|
||||
const char *propname, int index,
|
||||
enum gpiod_flags dflags,
|
||||
const char *label)
|
||||
@@ -680,10 +680,10 @@ struct acpi_gpio_mapping {
|
||||
unsigned int quirks;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_ACPI)
|
||||
|
||||
struct acpi_device;
|
||||
|
||||
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_ACPI)
|
||||
|
||||
int acpi_dev_add_driver_gpios(struct acpi_device *adev,
|
||||
const struct acpi_gpio_mapping *gpios);
|
||||
void acpi_dev_remove_driver_gpios(struct acpi_device *adev);
|
||||
@@ -696,8 +696,6 @@ struct gpio_desc *acpi_get_and_request_gpiod(char *path, int pin, char *label);
|
||||
|
||||
#else /* CONFIG_GPIOLIB && CONFIG_ACPI */
|
||||
|
||||
struct acpi_device;
|
||||
|
||||
static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev,
|
||||
const struct acpi_gpio_mapping *gpios)
|
||||
{
|
||||
|
||||
@@ -312,6 +312,9 @@ struct gpio_irq_chip {
|
||||
* get rid of the static GPIO number space in the long run.
|
||||
* @ngpio: the number of GPIOs handled by this controller; the last GPIO
|
||||
* handled is (base + ngpio - 1).
|
||||
* @offset: when multiple gpio chips belong to the same device this
|
||||
* can be used as offset within the device so friendly names can
|
||||
* be properly assigned.
|
||||
* @names: if set, must be an array of strings to use as alternative
|
||||
* names for the GPIOs in this chip. Any entry in the array
|
||||
* may be NULL if there is no alias for the GPIO, however the
|
||||
@@ -398,6 +401,7 @@ struct gpio_chip {
|
||||
|
||||
int base;
|
||||
u16 ngpio;
|
||||
u16 offset;
|
||||
const char *const *names;
|
||||
bool can_sleep;
|
||||
|
||||
|
||||
@@ -186,10 +186,11 @@ enum ddr_pwrst {
|
||||
#define PRCMU_FW_PROJECT_U8500_C3 8
|
||||
#define PRCMU_FW_PROJECT_U8500_C4 9
|
||||
#define PRCMU_FW_PROJECT_U9500_MBL 10
|
||||
#define PRCMU_FW_PROJECT_U8500_MBL 11 /* Customer specific */
|
||||
#define PRCMU_FW_PROJECT_U8500_SSG1 11 /* Samsung specific */
|
||||
#define PRCMU_FW_PROJECT_U8500_MBL2 12 /* Customer specific */
|
||||
#define PRCMU_FW_PROJECT_U8520 13
|
||||
#define PRCMU_FW_PROJECT_U8420 14
|
||||
#define PRCMU_FW_PROJECT_U8500_SSG2 15 /* Samsung specific */
|
||||
#define PRCMU_FW_PROJECT_U8420_SYSCLK 17
|
||||
#define PRCMU_FW_PROJECT_A9420 20
|
||||
/* [32..63] 9540 and derivatives */
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Register Map - Based on AN888_SMUforIEEE_SynchEther_82P33xxx_RevH.pdf
|
||||
*
|
||||
* Copyright (C) 2021 Integrated Device Technology, Inc., a Renesas Company.
|
||||
*/
|
||||
#ifndef HAVE_IDT82P33_REG
|
||||
#define HAVE_IDT82P33_REG
|
||||
|
||||
/* Register address */
|
||||
#define DPLL1_TOD_CNFG 0x134
|
||||
#define DPLL2_TOD_CNFG 0x1B4
|
||||
|
||||
#define DPLL1_TOD_STS 0x10B
|
||||
#define DPLL2_TOD_STS 0x18B
|
||||
|
||||
#define DPLL1_TOD_TRIGGER 0x115
|
||||
#define DPLL2_TOD_TRIGGER 0x195
|
||||
|
||||
#define DPLL1_OPERATING_MODE_CNFG 0x120
|
||||
#define DPLL2_OPERATING_MODE_CNFG 0x1A0
|
||||
|
||||
#define DPLL1_HOLDOVER_FREQ_CNFG 0x12C
|
||||
#define DPLL2_HOLDOVER_FREQ_CNFG 0x1AC
|
||||
|
||||
#define DPLL1_PHASE_OFFSET_CNFG 0x143
|
||||
#define DPLL2_PHASE_OFFSET_CNFG 0x1C3
|
||||
|
||||
#define DPLL1_SYNC_EDGE_CNFG 0x140
|
||||
#define DPLL2_SYNC_EDGE_CNFG 0x1C0
|
||||
|
||||
#define DPLL1_INPUT_MODE_CNFG 0x116
|
||||
#define DPLL2_INPUT_MODE_CNFG 0x196
|
||||
|
||||
#define DPLL1_OPERATING_STS 0x102
|
||||
#define DPLL2_OPERATING_STS 0x182
|
||||
|
||||
#define DPLL1_CURRENT_FREQ_STS 0x103
|
||||
#define DPLL2_CURRENT_FREQ_STS 0x183
|
||||
|
||||
#define REG_SOFT_RESET 0X381
|
||||
|
||||
#define OUT_MUX_CNFG(outn) REG_ADDR(0x6, (0xC * (outn)))
|
||||
|
||||
/* Register bit definitions */
|
||||
#define SYNC_TOD BIT(1)
|
||||
#define PH_OFFSET_EN BIT(7)
|
||||
#define SQUELCH_ENABLE BIT(5)
|
||||
|
||||
/* Bit definitions for the DPLL_MODE register */
|
||||
#define PLL_MODE_SHIFT (0)
|
||||
#define PLL_MODE_MASK (0x1F)
|
||||
#define COMBO_MODE_EN BIT(5)
|
||||
#define COMBO_MODE_SHIFT (6)
|
||||
#define COMBO_MODE_MASK (0x3)
|
||||
|
||||
/* Bit definitions for DPLL_OPERATING_STS register */
|
||||
#define OPERATING_STS_MASK (0x7)
|
||||
#define OPERATING_STS_SHIFT (0x0)
|
||||
|
||||
/* Bit definitions for DPLL_TOD_TRIGGER register */
|
||||
#define READ_TRIGGER_MASK (0xF)
|
||||
#define READ_TRIGGER_SHIFT (0x0)
|
||||
#define WRITE_TRIGGER_MASK (0xF0)
|
||||
#define WRITE_TRIGGER_SHIFT (0x4)
|
||||
|
||||
/* Bit definitions for REG_SOFT_RESET register */
|
||||
#define SOFT_RESET_EN BIT(7)
|
||||
|
||||
enum pll_mode {
|
||||
PLL_MODE_MIN = 0,
|
||||
PLL_MODE_AUTOMATIC = PLL_MODE_MIN,
|
||||
PLL_MODE_FORCE_FREERUN = 1,
|
||||
PLL_MODE_FORCE_HOLDOVER = 2,
|
||||
PLL_MODE_FORCE_LOCKED = 4,
|
||||
PLL_MODE_FORCE_PRE_LOCKED2 = 5,
|
||||
PLL_MODE_FORCE_PRE_LOCKED = 6,
|
||||
PLL_MODE_FORCE_LOST_PHASE = 7,
|
||||
PLL_MODE_DCO = 10,
|
||||
PLL_MODE_WPH = 18,
|
||||
PLL_MODE_MAX = PLL_MODE_WPH,
|
||||
};
|
||||
|
||||
enum hw_tod_trig_sel {
|
||||
HW_TOD_TRIG_SEL_MIN = 0,
|
||||
HW_TOD_TRIG_SEL_NO_WRITE = HW_TOD_TRIG_SEL_MIN,
|
||||
HW_TOD_TRIG_SEL_NO_READ = HW_TOD_TRIG_SEL_MIN,
|
||||
HW_TOD_TRIG_SEL_SYNC_SEL = 1,
|
||||
HW_TOD_TRIG_SEL_IN12 = 2,
|
||||
HW_TOD_TRIG_SEL_IN13 = 3,
|
||||
HW_TOD_TRIG_SEL_IN14 = 4,
|
||||
HW_TOD_TRIG_SEL_TOD_PPS = 5,
|
||||
HW_TOD_TRIG_SEL_TIMER_INTERVAL = 6,
|
||||
HW_TOD_TRIG_SEL_MSB_PHASE_OFFSET_CNFG = 7,
|
||||
HW_TOD_TRIG_SEL_MSB_HOLDOVER_FREQ_CNFG = 8,
|
||||
HW_TOD_WR_TRIG_SEL_MSB_TOD_CNFG = 9,
|
||||
HW_TOD_RD_TRIG_SEL_LSB_TOD_STS = HW_TOD_WR_TRIG_SEL_MSB_TOD_CNFG,
|
||||
WR_TRIG_SEL_MAX = HW_TOD_WR_TRIG_SEL_MSB_TOD_CNFG,
|
||||
};
|
||||
|
||||
/** @brief Enumerated type listing DPLL operational modes */
|
||||
enum dpll_state {
|
||||
DPLL_STATE_FREERUN = 1,
|
||||
DPLL_STATE_HOLDOVER = 2,
|
||||
DPLL_STATE_LOCKED = 4,
|
||||
DPLL_STATE_PRELOCKED2 = 5,
|
||||
DPLL_STATE_PRELOCKED = 6,
|
||||
DPLL_STATE_LOSTPHASE = 7,
|
||||
DPLL_STATE_MAX
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,729 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Based on 5.2.0, Family Programming Guide (Sept 30, 2020)
|
||||
*
|
||||
* Copyright (C) 2021 Integrated Device Technology, Inc., a Renesas Company.
|
||||
*/
|
||||
#ifndef HAVE_IDT8A340_REG
|
||||
#define HAVE_IDT8A340_REG
|
||||
|
||||
#define PAGE_ADDR_BASE 0x0000
|
||||
#define PAGE_ADDR 0x00fc
|
||||
|
||||
#define HW_REVISION 0x8180
|
||||
#define REV_ID 0x007a
|
||||
|
||||
#define HW_DPLL_0 (0x8a00)
|
||||
#define HW_DPLL_1 (0x8b00)
|
||||
#define HW_DPLL_2 (0x8c00)
|
||||
#define HW_DPLL_3 (0x8d00)
|
||||
#define HW_DPLL_4 (0x8e00)
|
||||
#define HW_DPLL_5 (0x8f00)
|
||||
#define HW_DPLL_6 (0x9000)
|
||||
#define HW_DPLL_7 (0x9100)
|
||||
|
||||
#define HW_DPLL_TOD_SW_TRIG_ADDR__0 (0x080)
|
||||
#define HW_DPLL_TOD_CTRL_1 (0x089)
|
||||
#define HW_DPLL_TOD_CTRL_2 (0x08A)
|
||||
#define HW_DPLL_TOD_OVR__0 (0x098)
|
||||
#define HW_DPLL_TOD_OUT_0__0 (0x0B0)
|
||||
|
||||
#define HW_Q0_Q1_CH_SYNC_CTRL_0 (0xa740)
|
||||
#define HW_Q0_Q1_CH_SYNC_CTRL_1 (0xa741)
|
||||
#define HW_Q2_Q3_CH_SYNC_CTRL_0 (0xa742)
|
||||
#define HW_Q2_Q3_CH_SYNC_CTRL_1 (0xa743)
|
||||
#define HW_Q4_Q5_CH_SYNC_CTRL_0 (0xa744)
|
||||
#define HW_Q4_Q5_CH_SYNC_CTRL_1 (0xa745)
|
||||
#define HW_Q6_Q7_CH_SYNC_CTRL_0 (0xa746)
|
||||
#define HW_Q6_Q7_CH_SYNC_CTRL_1 (0xa747)
|
||||
#define HW_Q8_CH_SYNC_CTRL_0 (0xa748)
|
||||
#define HW_Q8_CH_SYNC_CTRL_1 (0xa749)
|
||||
#define HW_Q9_CH_SYNC_CTRL_0 (0xa74a)
|
||||
#define HW_Q9_CH_SYNC_CTRL_1 (0xa74b)
|
||||
#define HW_Q10_CH_SYNC_CTRL_0 (0xa74c)
|
||||
#define HW_Q10_CH_SYNC_CTRL_1 (0xa74d)
|
||||
#define HW_Q11_CH_SYNC_CTRL_0 (0xa74e)
|
||||
#define HW_Q11_CH_SYNC_CTRL_1 (0xa74f)
|
||||
|
||||
#define SYNC_SOURCE_DPLL0_TOD_PPS 0x14
|
||||
#define SYNC_SOURCE_DPLL1_TOD_PPS 0x15
|
||||
#define SYNC_SOURCE_DPLL2_TOD_PPS 0x16
|
||||
#define SYNC_SOURCE_DPLL3_TOD_PPS 0x17
|
||||
|
||||
#define SYNCTRL1_MASTER_SYNC_RST BIT(7)
|
||||
#define SYNCTRL1_MASTER_SYNC_TRIG BIT(5)
|
||||
#define SYNCTRL1_TOD_SYNC_TRIG BIT(4)
|
||||
#define SYNCTRL1_FBDIV_FRAME_SYNC_TRIG BIT(3)
|
||||
#define SYNCTRL1_FBDIV_SYNC_TRIG BIT(2)
|
||||
#define SYNCTRL1_Q1_DIV_SYNC_TRIG BIT(1)
|
||||
#define SYNCTRL1_Q0_DIV_SYNC_TRIG BIT(0)
|
||||
|
||||
#define HW_Q8_CTRL_SPARE (0xa7d4)
|
||||
#define HW_Q11_CTRL_SPARE (0xa7ec)
|
||||
|
||||
/**
|
||||
* Select FOD5 as sync_trigger for Q8 divider.
|
||||
* Transition from logic zero to one
|
||||
* sets trigger to sync Q8 divider.
|
||||
*
|
||||
* Unused when FOD4 is driving Q8 divider (normal operation).
|
||||
*/
|
||||
#define Q9_TO_Q8_SYNC_TRIG BIT(1)
|
||||
|
||||
/**
|
||||
* Enable FOD5 as driver for clock and sync for Q8 divider.
|
||||
* Enable fanout buffer for FOD5.
|
||||
*
|
||||
* Unused when FOD4 is driving Q8 divider (normal operation).
|
||||
*/
|
||||
#define Q9_TO_Q8_FANOUT_AND_CLOCK_SYNC_ENABLE_MASK (BIT(0) | BIT(2))
|
||||
|
||||
/**
|
||||
* Select FOD6 as sync_trigger for Q11 divider.
|
||||
* Transition from logic zero to one
|
||||
* sets trigger to sync Q11 divider.
|
||||
*
|
||||
* Unused when FOD7 is driving Q11 divider (normal operation).
|
||||
*/
|
||||
#define Q10_TO_Q11_SYNC_TRIG BIT(1)
|
||||
|
||||
/**
|
||||
* Enable FOD6 as driver for clock and sync for Q11 divider.
|
||||
* Enable fanout buffer for FOD6.
|
||||
*
|
||||
* Unused when FOD7 is driving Q11 divider (normal operation).
|
||||
*/
|
||||
#define Q10_TO_Q11_FANOUT_AND_CLOCK_SYNC_ENABLE_MASK (BIT(0) | BIT(2))
|
||||
|
||||
#define RESET_CTRL 0xc000
|
||||
#define SM_RESET 0x0012
|
||||
#define SM_RESET_V520 0x0013
|
||||
#define SM_RESET_CMD 0x5A
|
||||
|
||||
#define GENERAL_STATUS 0xc014
|
||||
#define BOOT_STATUS 0x0000
|
||||
#define HW_REV_ID 0x000A
|
||||
#define BOND_ID 0x000B
|
||||
#define HW_CSR_ID 0x000C
|
||||
#define HW_IRQ_ID 0x000E
|
||||
#define MAJ_REL 0x0010
|
||||
#define MIN_REL 0x0011
|
||||
#define HOTFIX_REL 0x0012
|
||||
#define PIPELINE_ID 0x0014
|
||||
#define BUILD_ID 0x0018
|
||||
#define JTAG_DEVICE_ID 0x001c
|
||||
#define PRODUCT_ID 0x001e
|
||||
#define OTP_SCSR_CONFIG_SELECT 0x0022
|
||||
|
||||
#define STATUS 0xc03c
|
||||
#define DPLL0_STATUS 0x0018
|
||||
#define DPLL1_STATUS 0x0019
|
||||
#define DPLL2_STATUS 0x001a
|
||||
#define DPLL3_STATUS 0x001b
|
||||
#define DPLL4_STATUS 0x001c
|
||||
#define DPLL5_STATUS 0x001d
|
||||
#define DPLL6_STATUS 0x001e
|
||||
#define DPLL7_STATUS 0x001f
|
||||
#define DPLL_SYS_STATUS 0x0020
|
||||
#define DPLL_SYS_APLL_STATUS 0x0021
|
||||
#define DPLL0_FILTER_STATUS 0x0044
|
||||
#define DPLL1_FILTER_STATUS 0x004c
|
||||
#define DPLL2_FILTER_STATUS 0x0054
|
||||
#define DPLL3_FILTER_STATUS 0x005c
|
||||
#define DPLL4_FILTER_STATUS 0x0064
|
||||
#define DPLL5_FILTER_STATUS 0x006c
|
||||
#define DPLL6_FILTER_STATUS 0x0074
|
||||
#define DPLL7_FILTER_STATUS 0x007c
|
||||
#define DPLLSYS_FILTER_STATUS 0x0084
|
||||
#define USER_GPIO0_TO_7_STATUS 0x008a
|
||||
#define USER_GPIO8_TO_15_STATUS 0x008b
|
||||
|
||||
#define GPIO_USER_CONTROL 0xc160
|
||||
#define GPIO0_TO_7_OUT 0x0000
|
||||
#define GPIO8_TO_15_OUT 0x0001
|
||||
#define GPIO0_TO_7_OUT_V520 0x0002
|
||||
#define GPIO8_TO_15_OUT_V520 0x0003
|
||||
|
||||
#define STICKY_STATUS_CLEAR 0xc164
|
||||
|
||||
#define GPIO_TOD_NOTIFICATION_CLEAR 0xc16c
|
||||
|
||||
#define ALERT_CFG 0xc188
|
||||
|
||||
#define SYS_DPLL_XO 0xc194
|
||||
|
||||
#define SYS_APLL 0xc19c
|
||||
|
||||
#define INPUT_0 0xc1b0
|
||||
#define INPUT_1 0xc1c0
|
||||
#define INPUT_2 0xc1d0
|
||||
#define INPUT_3 0xc200
|
||||
#define INPUT_4 0xc210
|
||||
#define INPUT_5 0xc220
|
||||
#define INPUT_6 0xc230
|
||||
#define INPUT_7 0xc240
|
||||
#define INPUT_8 0xc250
|
||||
#define INPUT_9 0xc260
|
||||
#define INPUT_10 0xc280
|
||||
#define INPUT_11 0xc290
|
||||
#define INPUT_12 0xc2a0
|
||||
#define INPUT_13 0xc2b0
|
||||
#define INPUT_14 0xc2c0
|
||||
#define INPUT_15 0xc2d0
|
||||
|
||||
#define REF_MON_0 0xc2e0
|
||||
#define REF_MON_1 0xc2ec
|
||||
#define REF_MON_2 0xc300
|
||||
#define REF_MON_3 0xc30c
|
||||
#define REF_MON_4 0xc318
|
||||
#define REF_MON_5 0xc324
|
||||
#define REF_MON_6 0xc330
|
||||
#define REF_MON_7 0xc33c
|
||||
#define REF_MON_8 0xc348
|
||||
#define REF_MON_9 0xc354
|
||||
#define REF_MON_10 0xc360
|
||||
#define REF_MON_11 0xc36c
|
||||
#define REF_MON_12 0xc380
|
||||
#define REF_MON_13 0xc38c
|
||||
#define REF_MON_14 0xc398
|
||||
#define REF_MON_15 0xc3a4
|
||||
|
||||
#define DPLL_0 0xc3b0
|
||||
#define DPLL_CTRL_REG_0 0x0002
|
||||
#define DPLL_CTRL_REG_1 0x0003
|
||||
#define DPLL_CTRL_REG_2 0x0004
|
||||
#define DPLL_TOD_SYNC_CFG 0x0031
|
||||
#define DPLL_COMBO_SLAVE_CFG_0 0x0032
|
||||
#define DPLL_COMBO_SLAVE_CFG_1 0x0033
|
||||
#define DPLL_SLAVE_REF_CFG 0x0034
|
||||
#define DPLL_REF_MODE 0x0035
|
||||
#define DPLL_PHASE_MEASUREMENT_CFG 0x0036
|
||||
#define DPLL_MODE 0x0037
|
||||
#define DPLL_MODE_V520 0x003B
|
||||
#define DPLL_1 0xc400
|
||||
#define DPLL_2 0xc438
|
||||
#define DPLL_2_V520 0xc43c
|
||||
#define DPLL_3 0xc480
|
||||
#define DPLL_4 0xc4b8
|
||||
#define DPLL_4_V520 0xc4bc
|
||||
#define DPLL_5 0xc500
|
||||
#define DPLL_6 0xc538
|
||||
#define DPLL_6_V520 0xc53c
|
||||
#define DPLL_7 0xc580
|
||||
#define SYS_DPLL 0xc5b8
|
||||
#define SYS_DPLL_V520 0xc5bc
|
||||
|
||||
#define DPLL_CTRL_0 0xc600
|
||||
#define DPLL_CTRL_DPLL_MANU_REF_CFG 0x0001
|
||||
#define DPLL_CTRL_DPLL_FOD_FREQ 0x001c
|
||||
#define DPLL_CTRL_COMBO_MASTER_CFG 0x003a
|
||||
#define DPLL_CTRL_1 0xc63c
|
||||
#define DPLL_CTRL_2 0xc680
|
||||
#define DPLL_CTRL_3 0xc6bc
|
||||
#define DPLL_CTRL_4 0xc700
|
||||
#define DPLL_CTRL_5 0xc73c
|
||||
#define DPLL_CTRL_6 0xc780
|
||||
#define DPLL_CTRL_7 0xc7bc
|
||||
#define SYS_DPLL_CTRL 0xc800
|
||||
|
||||
#define DPLL_PHASE_0 0xc818
|
||||
/* Signed 42-bit FFO in units of 2^(-53) */
|
||||
#define DPLL_WR_PHASE 0x0000
|
||||
#define DPLL_PHASE_1 0xc81c
|
||||
#define DPLL_PHASE_2 0xc820
|
||||
#define DPLL_PHASE_3 0xc824
|
||||
#define DPLL_PHASE_4 0xc828
|
||||
#define DPLL_PHASE_5 0xc82c
|
||||
#define DPLL_PHASE_6 0xc830
|
||||
#define DPLL_PHASE_7 0xc834
|
||||
|
||||
#define DPLL_FREQ_0 0xc838
|
||||
/* Signed 42-bit FFO in units of 2^(-53) */
|
||||
#define DPLL_WR_FREQ 0x0000
|
||||
#define DPLL_FREQ_1 0xc840
|
||||
#define DPLL_FREQ_2 0xc848
|
||||
#define DPLL_FREQ_3 0xc850
|
||||
#define DPLL_FREQ_4 0xc858
|
||||
#define DPLL_FREQ_5 0xc860
|
||||
#define DPLL_FREQ_6 0xc868
|
||||
#define DPLL_FREQ_7 0xc870
|
||||
|
||||
#define DPLL_PHASE_PULL_IN_0 0xc880
|
||||
#define PULL_IN_OFFSET 0x0000 /* Signed 32 bit */
|
||||
#define PULL_IN_SLOPE_LIMIT 0x0004 /* Unsigned 24 bit */
|
||||
#define PULL_IN_CTRL 0x0007
|
||||
#define DPLL_PHASE_PULL_IN_1 0xc888
|
||||
#define DPLL_PHASE_PULL_IN_2 0xc890
|
||||
#define DPLL_PHASE_PULL_IN_3 0xc898
|
||||
#define DPLL_PHASE_PULL_IN_4 0xc8a0
|
||||
#define DPLL_PHASE_PULL_IN_5 0xc8a8
|
||||
#define DPLL_PHASE_PULL_IN_6 0xc8b0
|
||||
#define DPLL_PHASE_PULL_IN_7 0xc8b8
|
||||
|
||||
#define GPIO_CFG 0xc8c0
|
||||
#define GPIO_CFG_GBL 0x0000
|
||||
#define GPIO_0 0xc8c2
|
||||
#define GPIO_DCO_INC_DEC 0x0000
|
||||
#define GPIO_OUT_CTRL_0 0x0001
|
||||
#define GPIO_OUT_CTRL_1 0x0002
|
||||
#define GPIO_TOD_TRIG 0x0003
|
||||
#define GPIO_DPLL_INDICATOR 0x0004
|
||||
#define GPIO_LOS_INDICATOR 0x0005
|
||||
#define GPIO_REF_INPUT_DSQ_0 0x0006
|
||||
#define GPIO_REF_INPUT_DSQ_1 0x0007
|
||||
#define GPIO_REF_INPUT_DSQ_2 0x0008
|
||||
#define GPIO_REF_INPUT_DSQ_3 0x0009
|
||||
#define GPIO_MAN_CLK_SEL_0 0x000a
|
||||
#define GPIO_MAN_CLK_SEL_1 0x000b
|
||||
#define GPIO_MAN_CLK_SEL_2 0x000c
|
||||
#define GPIO_SLAVE 0x000d
|
||||
#define GPIO_ALERT_OUT_CFG 0x000e
|
||||
#define GPIO_TOD_NOTIFICATION_CFG 0x000f
|
||||
#define GPIO_CTRL 0x0010
|
||||
#define GPIO_CTRL_V520 0x0011
|
||||
#define GPIO_1 0xc8d4
|
||||
#define GPIO_2 0xc8e6
|
||||
#define GPIO_3 0xc900
|
||||
#define GPIO_4 0xc912
|
||||
#define GPIO_5 0xc924
|
||||
#define GPIO_6 0xc936
|
||||
#define GPIO_7 0xc948
|
||||
#define GPIO_8 0xc95a
|
||||
#define GPIO_9 0xc980
|
||||
#define GPIO_10 0xc992
|
||||
#define GPIO_11 0xc9a4
|
||||
#define GPIO_12 0xc9b6
|
||||
#define GPIO_13 0xc9c8
|
||||
#define GPIO_14 0xc9da
|
||||
#define GPIO_15 0xca00
|
||||
|
||||
#define OUT_DIV_MUX 0xca12
|
||||
#define OUTPUT_0 0xca14
|
||||
#define OUTPUT_0_V520 0xca20
|
||||
/* FOD frequency output divider value */
|
||||
#define OUT_DIV 0x0000
|
||||
#define OUT_DUTY_CYCLE_HIGH 0x0004
|
||||
#define OUT_CTRL_0 0x0008
|
||||
#define OUT_CTRL_1 0x0009
|
||||
/* Phase adjustment in FOD cycles */
|
||||
#define OUT_PHASE_ADJ 0x000c
|
||||
#define OUTPUT_1 0xca24
|
||||
#define OUTPUT_1_V520 0xca30
|
||||
#define OUTPUT_2 0xca34
|
||||
#define OUTPUT_2_V520 0xca40
|
||||
#define OUTPUT_3 0xca44
|
||||
#define OUTPUT_3_V520 0xca50
|
||||
#define OUTPUT_4 0xca54
|
||||
#define OUTPUT_4_V520 0xca60
|
||||
#define OUTPUT_5 0xca64
|
||||
#define OUTPUT_5_V520 0xca80
|
||||
#define OUTPUT_6 0xca80
|
||||
#define OUTPUT_6_V520 0xca90
|
||||
#define OUTPUT_7 0xca90
|
||||
#define OUTPUT_7_V520 0xcaa0
|
||||
#define OUTPUT_8 0xcaa0
|
||||
#define OUTPUT_8_V520 0xcab0
|
||||
#define OUTPUT_9 0xcab0
|
||||
#define OUTPUT_9_V520 0xcac0
|
||||
#define OUTPUT_10 0xcac0
|
||||
#define OUTPUT_10_V520 0xcad0
|
||||
#define OUTPUT_11 0xcad0
|
||||
#define OUTPUT_11_V520 0xcae0
|
||||
|
||||
#define SERIAL 0xcae0
|
||||
#define SERIAL_V520 0xcaf0
|
||||
|
||||
#define PWM_ENCODER_0 0xcb00
|
||||
#define PWM_ENCODER_1 0xcb08
|
||||
#define PWM_ENCODER_2 0xcb10
|
||||
#define PWM_ENCODER_3 0xcb18
|
||||
#define PWM_ENCODER_4 0xcb20
|
||||
#define PWM_ENCODER_5 0xcb28
|
||||
#define PWM_ENCODER_6 0xcb30
|
||||
#define PWM_ENCODER_7 0xcb38
|
||||
#define PWM_DECODER_0 0xcb40
|
||||
#define PWM_DECODER_1 0xcb48
|
||||
#define PWM_DECODER_1_V520 0xcb4a
|
||||
#define PWM_DECODER_2 0xcb50
|
||||
#define PWM_DECODER_2_V520 0xcb54
|
||||
#define PWM_DECODER_3 0xcb58
|
||||
#define PWM_DECODER_3_V520 0xcb5e
|
||||
#define PWM_DECODER_4 0xcb60
|
||||
#define PWM_DECODER_4_V520 0xcb68
|
||||
#define PWM_DECODER_5 0xcb68
|
||||
#define PWM_DECODER_5_V520 0xcb80
|
||||
#define PWM_DECODER_6 0xcb70
|
||||
#define PWM_DECODER_6_V520 0xcb8a
|
||||
#define PWM_DECODER_7 0xcb80
|
||||
#define PWM_DECODER_7_V520 0xcb94
|
||||
#define PWM_DECODER_8 0xcb88
|
||||
#define PWM_DECODER_8_V520 0xcb9e
|
||||
#define PWM_DECODER_9 0xcb90
|
||||
#define PWM_DECODER_9_V520 0xcba8
|
||||
#define PWM_DECODER_10 0xcb98
|
||||
#define PWM_DECODER_10_V520 0xcbb2
|
||||
#define PWM_DECODER_11 0xcba0
|
||||
#define PWM_DECODER_11_V520 0xcbbc
|
||||
#define PWM_DECODER_12 0xcba8
|
||||
#define PWM_DECODER_12_V520 0xcbc6
|
||||
#define PWM_DECODER_13 0xcbb0
|
||||
#define PWM_DECODER_13_V520 0xcbd0
|
||||
#define PWM_DECODER_14 0xcbb8
|
||||
#define PWM_DECODER_14_V520 0xcbda
|
||||
#define PWM_DECODER_15 0xcbc0
|
||||
#define PWM_DECODER_15_V520 0xcbe4
|
||||
#define PWM_USER_DATA 0xcbc8
|
||||
#define PWM_USER_DATA_V520 0xcbf0
|
||||
|
||||
#define TOD_0 0xcbcc
|
||||
#define TOD_0_V520 0xcc00
|
||||
/* Enable TOD counter, output channel sync and even-PPS mode */
|
||||
#define TOD_CFG 0x0000
|
||||
#define TOD_CFG_V520 0x0001
|
||||
#define TOD_1 0xcbce
|
||||
#define TOD_1_V520 0xcc02
|
||||
#define TOD_2 0xcbd0
|
||||
#define TOD_2_V520 0xcc04
|
||||
#define TOD_3 0xcbd2
|
||||
#define TOD_3_V520 0xcc06
|
||||
|
||||
#define TOD_WRITE_0 0xcc00
|
||||
#define TOD_WRITE_0_V520 0xcc10
|
||||
/* 8-bit subns, 32-bit ns, 48-bit seconds */
|
||||
#define TOD_WRITE 0x0000
|
||||
/* Counter increments after TOD write is completed */
|
||||
#define TOD_WRITE_COUNTER 0x000c
|
||||
/* TOD write trigger configuration */
|
||||
#define TOD_WRITE_SELECT_CFG_0 0x000d
|
||||
/* TOD write trigger selection */
|
||||
#define TOD_WRITE_CMD 0x000f
|
||||
#define TOD_WRITE_1 0xcc10
|
||||
#define TOD_WRITE_1_V520 0xcc20
|
||||
#define TOD_WRITE_2 0xcc20
|
||||
#define TOD_WRITE_2_V520 0xcc30
|
||||
#define TOD_WRITE_3 0xcc30
|
||||
#define TOD_WRITE_3_V520 0xcc40
|
||||
|
||||
#define TOD_READ_PRIMARY_0 0xcc40
|
||||
#define TOD_READ_PRIMARY_0_V520 0xcc50
|
||||
/* 8-bit subns, 32-bit ns, 48-bit seconds */
|
||||
#define TOD_READ_PRIMARY 0x0000
|
||||
/* Counter increments after TOD write is completed */
|
||||
#define TOD_READ_PRIMARY_COUNTER 0x000b
|
||||
/* Read trigger configuration */
|
||||
#define TOD_READ_PRIMARY_SEL_CFG_0 0x000c
|
||||
/* Read trigger selection */
|
||||
#define TOD_READ_PRIMARY_CMD 0x000e
|
||||
#define TOD_READ_PRIMARY_CMD_V520 0x000f
|
||||
#define TOD_READ_PRIMARY_1 0xcc50
|
||||
#define TOD_READ_PRIMARY_1_V520 0xcc60
|
||||
#define TOD_READ_PRIMARY_2 0xcc60
|
||||
#define TOD_READ_PRIMARY_2_V520 0xcc80
|
||||
#define TOD_READ_PRIMARY_3 0xcc80
|
||||
#define TOD_READ_PRIMARY_3_V520 0xcc90
|
||||
|
||||
#define TOD_READ_SECONDARY_0 0xcc90
|
||||
#define TOD_READ_SECONDARY_0_V520 0xcca0
|
||||
#define TOD_READ_SECONDARY_1 0xcca0
|
||||
#define TOD_READ_SECONDARY_1_V520 0xccb0
|
||||
#define TOD_READ_SECONDARY_2 0xccb0
|
||||
#define TOD_READ_SECONDARY_2_V520 0xccc0
|
||||
#define TOD_READ_SECONDARY_3 0xccc0
|
||||
#define TOD_READ_SECONDARY_3_V520 0xccd0
|
||||
|
||||
#define OUTPUT_TDC_CFG 0xccd0
|
||||
#define OUTPUT_TDC_CFG_V520 0xcce0
|
||||
#define OUTPUT_TDC_0 0xcd00
|
||||
#define OUTPUT_TDC_1 0xcd08
|
||||
#define OUTPUT_TDC_2 0xcd10
|
||||
#define OUTPUT_TDC_3 0xcd18
|
||||
#define INPUT_TDC 0xcd20
|
||||
|
||||
#define SCRATCH 0xcf50
|
||||
#define SCRATCH_V520 0xcf4c
|
||||
|
||||
#define EEPROM 0xcf68
|
||||
#define EEPROM_V520 0xcf64
|
||||
|
||||
#define OTP 0xcf70
|
||||
|
||||
#define BYTE 0xcf80
|
||||
|
||||
/* Bit definitions for the MAJ_REL register */
|
||||
#define MAJOR_SHIFT (1)
|
||||
#define MAJOR_MASK (0x7f)
|
||||
#define PR_BUILD BIT(0)
|
||||
|
||||
/* Bit definitions for the USER_GPIO0_TO_7_STATUS register */
|
||||
#define GPIO0_LEVEL BIT(0)
|
||||
#define GPIO1_LEVEL BIT(1)
|
||||
#define GPIO2_LEVEL BIT(2)
|
||||
#define GPIO3_LEVEL BIT(3)
|
||||
#define GPIO4_LEVEL BIT(4)
|
||||
#define GPIO5_LEVEL BIT(5)
|
||||
#define GPIO6_LEVEL BIT(6)
|
||||
#define GPIO7_LEVEL BIT(7)
|
||||
|
||||
/* Bit definitions for the USER_GPIO8_TO_15_STATUS register */
|
||||
#define GPIO8_LEVEL BIT(0)
|
||||
#define GPIO9_LEVEL BIT(1)
|
||||
#define GPIO10_LEVEL BIT(2)
|
||||
#define GPIO11_LEVEL BIT(3)
|
||||
#define GPIO12_LEVEL BIT(4)
|
||||
#define GPIO13_LEVEL BIT(5)
|
||||
#define GPIO14_LEVEL BIT(6)
|
||||
#define GPIO15_LEVEL BIT(7)
|
||||
|
||||
/* Bit definitions for the GPIO0_TO_7_OUT register */
|
||||
#define GPIO0_DRIVE_LEVEL BIT(0)
|
||||
#define GPIO1_DRIVE_LEVEL BIT(1)
|
||||
#define GPIO2_DRIVE_LEVEL BIT(2)
|
||||
#define GPIO3_DRIVE_LEVEL BIT(3)
|
||||
#define GPIO4_DRIVE_LEVEL BIT(4)
|
||||
#define GPIO5_DRIVE_LEVEL BIT(5)
|
||||
#define GPIO6_DRIVE_LEVEL BIT(6)
|
||||
#define GPIO7_DRIVE_LEVEL BIT(7)
|
||||
|
||||
/* Bit definitions for the GPIO8_TO_15_OUT register */
|
||||
#define GPIO8_DRIVE_LEVEL BIT(0)
|
||||
#define GPIO9_DRIVE_LEVEL BIT(1)
|
||||
#define GPIO10_DRIVE_LEVEL BIT(2)
|
||||
#define GPIO11_DRIVE_LEVEL BIT(3)
|
||||
#define GPIO12_DRIVE_LEVEL BIT(4)
|
||||
#define GPIO13_DRIVE_LEVEL BIT(5)
|
||||
#define GPIO14_DRIVE_LEVEL BIT(6)
|
||||
#define GPIO15_DRIVE_LEVEL BIT(7)
|
||||
|
||||
/* Bit definitions for the DPLL_TOD_SYNC_CFG register */
|
||||
#define TOD_SYNC_SOURCE_SHIFT (1)
|
||||
#define TOD_SYNC_SOURCE_MASK (0x3)
|
||||
#define TOD_SYNC_EN BIT(0)
|
||||
|
||||
/* Bit definitions for the DPLL_MODE register */
|
||||
#define WRITE_TIMER_MODE BIT(6)
|
||||
#define PLL_MODE_SHIFT (3)
|
||||
#define PLL_MODE_MASK (0x7)
|
||||
#define STATE_MODE_SHIFT (0)
|
||||
#define STATE_MODE_MASK (0x7)
|
||||
|
||||
/* Bit definitions for the GPIO_CFG_GBL register */
|
||||
#define SUPPLY_MODE_SHIFT (0)
|
||||
#define SUPPLY_MODE_MASK (0x3)
|
||||
|
||||
/* Bit definitions for the GPIO_DCO_INC_DEC register */
|
||||
#define INCDEC_DPLL_INDEX_SHIFT (0)
|
||||
#define INCDEC_DPLL_INDEX_MASK (0x7)
|
||||
|
||||
/* Bit definitions for the GPIO_OUT_CTRL_0 register */
|
||||
#define CTRL_OUT_0 BIT(0)
|
||||
#define CTRL_OUT_1 BIT(1)
|
||||
#define CTRL_OUT_2 BIT(2)
|
||||
#define CTRL_OUT_3 BIT(3)
|
||||
#define CTRL_OUT_4 BIT(4)
|
||||
#define CTRL_OUT_5 BIT(5)
|
||||
#define CTRL_OUT_6 BIT(6)
|
||||
#define CTRL_OUT_7 BIT(7)
|
||||
|
||||
/* Bit definitions for the GPIO_OUT_CTRL_1 register */
|
||||
#define CTRL_OUT_8 BIT(0)
|
||||
#define CTRL_OUT_9 BIT(1)
|
||||
#define CTRL_OUT_10 BIT(2)
|
||||
#define CTRL_OUT_11 BIT(3)
|
||||
#define CTRL_OUT_12 BIT(4)
|
||||
#define CTRL_OUT_13 BIT(5)
|
||||
#define CTRL_OUT_14 BIT(6)
|
||||
#define CTRL_OUT_15 BIT(7)
|
||||
|
||||
/* Bit definitions for the GPIO_TOD_TRIG register */
|
||||
#define TOD_TRIG_0 BIT(0)
|
||||
#define TOD_TRIG_1 BIT(1)
|
||||
#define TOD_TRIG_2 BIT(2)
|
||||
#define TOD_TRIG_3 BIT(3)
|
||||
|
||||
/* Bit definitions for the GPIO_DPLL_INDICATOR register */
|
||||
#define IND_DPLL_INDEX_SHIFT (0)
|
||||
#define IND_DPLL_INDEX_MASK (0x7)
|
||||
|
||||
/* Bit definitions for the GPIO_LOS_INDICATOR register */
|
||||
#define REFMON_INDEX_SHIFT (0)
|
||||
#define REFMON_INDEX_MASK (0xf)
|
||||
/* Active level of LOS indicator, 0=low 1=high */
|
||||
#define ACTIVE_LEVEL BIT(4)
|
||||
|
||||
/* Bit definitions for the GPIO_REF_INPUT_DSQ_0 register */
|
||||
#define DSQ_INP_0 BIT(0)
|
||||
#define DSQ_INP_1 BIT(1)
|
||||
#define DSQ_INP_2 BIT(2)
|
||||
#define DSQ_INP_3 BIT(3)
|
||||
#define DSQ_INP_4 BIT(4)
|
||||
#define DSQ_INP_5 BIT(5)
|
||||
#define DSQ_INP_6 BIT(6)
|
||||
#define DSQ_INP_7 BIT(7)
|
||||
|
||||
/* Bit definitions for the GPIO_REF_INPUT_DSQ_1 register */
|
||||
#define DSQ_INP_8 BIT(0)
|
||||
#define DSQ_INP_9 BIT(1)
|
||||
#define DSQ_INP_10 BIT(2)
|
||||
#define DSQ_INP_11 BIT(3)
|
||||
#define DSQ_INP_12 BIT(4)
|
||||
#define DSQ_INP_13 BIT(5)
|
||||
#define DSQ_INP_14 BIT(6)
|
||||
#define DSQ_INP_15 BIT(7)
|
||||
|
||||
/* Bit definitions for the GPIO_REF_INPUT_DSQ_2 register */
|
||||
#define DSQ_DPLL_0 BIT(0)
|
||||
#define DSQ_DPLL_1 BIT(1)
|
||||
#define DSQ_DPLL_2 BIT(2)
|
||||
#define DSQ_DPLL_3 BIT(3)
|
||||
#define DSQ_DPLL_4 BIT(4)
|
||||
#define DSQ_DPLL_5 BIT(5)
|
||||
#define DSQ_DPLL_6 BIT(6)
|
||||
#define DSQ_DPLL_7 BIT(7)
|
||||
|
||||
/* Bit definitions for the GPIO_REF_INPUT_DSQ_3 register */
|
||||
#define DSQ_DPLL_SYS BIT(0)
|
||||
#define GPIO_DSQ_LEVEL BIT(1)
|
||||
|
||||
/* Bit definitions for the GPIO_TOD_NOTIFICATION_CFG register */
|
||||
#define DPLL_TOD_SHIFT (0)
|
||||
#define DPLL_TOD_MASK (0x3)
|
||||
#define TOD_READ_SECONDARY BIT(2)
|
||||
#define GPIO_ASSERT_LEVEL BIT(3)
|
||||
|
||||
/* Bit definitions for the GPIO_CTRL register */
|
||||
#define GPIO_FUNCTION_EN BIT(0)
|
||||
#define GPIO_CMOS_OD_MODE BIT(1)
|
||||
#define GPIO_CONTROL_DIR BIT(2)
|
||||
#define GPIO_PU_PD_MODE BIT(3)
|
||||
#define GPIO_FUNCTION_SHIFT (4)
|
||||
#define GPIO_FUNCTION_MASK (0xf)
|
||||
|
||||
/* Bit definitions for the OUT_CTRL_1 register */
|
||||
#define OUT_SYNC_DISABLE BIT(7)
|
||||
#define SQUELCH_VALUE BIT(6)
|
||||
#define SQUELCH_DISABLE BIT(5)
|
||||
#define PAD_VDDO_SHIFT (2)
|
||||
#define PAD_VDDO_MASK (0x7)
|
||||
#define PAD_CMOSDRV_SHIFT (0)
|
||||
#define PAD_CMOSDRV_MASK (0x3)
|
||||
|
||||
/* Bit definitions for the TOD_CFG register */
|
||||
#define TOD_EVEN_PPS_MODE BIT(2)
|
||||
#define TOD_OUT_SYNC_ENABLE BIT(1)
|
||||
#define TOD_ENABLE BIT(0)
|
||||
|
||||
/* Bit definitions for the TOD_WRITE_SELECT_CFG_0 register */
|
||||
#define WR_PWM_DECODER_INDEX_SHIFT (4)
|
||||
#define WR_PWM_DECODER_INDEX_MASK (0xf)
|
||||
#define WR_REF_INDEX_SHIFT (0)
|
||||
#define WR_REF_INDEX_MASK (0xf)
|
||||
|
||||
/* Bit definitions for the TOD_WRITE_CMD register */
|
||||
#define TOD_WRITE_SELECTION_SHIFT (0)
|
||||
#define TOD_WRITE_SELECTION_MASK (0xf)
|
||||
/* 4.8.7 */
|
||||
#define TOD_WRITE_TYPE_SHIFT (4)
|
||||
#define TOD_WRITE_TYPE_MASK (0x3)
|
||||
|
||||
/* Bit definitions for the TOD_READ_PRIMARY_SEL_CFG_0 register */
|
||||
#define RD_PWM_DECODER_INDEX_SHIFT (4)
|
||||
#define RD_PWM_DECODER_INDEX_MASK (0xf)
|
||||
#define RD_REF_INDEX_SHIFT (0)
|
||||
#define RD_REF_INDEX_MASK (0xf)
|
||||
|
||||
/* Bit definitions for the TOD_READ_PRIMARY_CMD register */
|
||||
#define TOD_READ_TRIGGER_MODE BIT(4)
|
||||
#define TOD_READ_TRIGGER_SHIFT (0)
|
||||
#define TOD_READ_TRIGGER_MASK (0xf)
|
||||
|
||||
/* Bit definitions for the DPLL_CTRL_COMBO_MASTER_CFG register */
|
||||
#define COMBO_MASTER_HOLD BIT(0)
|
||||
|
||||
/* Bit definitions for DPLL_SYS_STATUS register */
|
||||
#define DPLL_SYS_STATE_MASK (0xf)
|
||||
|
||||
/* Bit definitions for SYS_APLL_STATUS register */
|
||||
#define SYS_APLL_LOSS_LOCK_LIVE_MASK BIT(0)
|
||||
#define SYS_APLL_LOSS_LOCK_LIVE_LOCKED 0
|
||||
#define SYS_APLL_LOSS_LOCK_LIVE_UNLOCKED 1
|
||||
|
||||
/* Bit definitions for the DPLL0_STATUS register */
|
||||
#define DPLL_STATE_MASK (0xf)
|
||||
#define DPLL_STATE_SHIFT (0x0)
|
||||
|
||||
/* Values of DPLL_N.DPLL_MODE.PLL_MODE */
|
||||
enum pll_mode {
|
||||
PLL_MODE_MIN = 0,
|
||||
PLL_MODE_NORMAL = PLL_MODE_MIN,
|
||||
PLL_MODE_WRITE_PHASE = 1,
|
||||
PLL_MODE_WRITE_FREQUENCY = 2,
|
||||
PLL_MODE_GPIO_INC_DEC = 3,
|
||||
PLL_MODE_SYNTHESIS = 4,
|
||||
PLL_MODE_PHASE_MEASUREMENT = 5,
|
||||
PLL_MODE_DISABLED = 6,
|
||||
PLL_MODE_MAX = PLL_MODE_DISABLED,
|
||||
};
|
||||
|
||||
enum hw_tod_write_trig_sel {
|
||||
HW_TOD_WR_TRIG_SEL_MIN = 0,
|
||||
HW_TOD_WR_TRIG_SEL_MSB = HW_TOD_WR_TRIG_SEL_MIN,
|
||||
HW_TOD_WR_TRIG_SEL_RESERVED = 1,
|
||||
HW_TOD_WR_TRIG_SEL_TOD_PPS = 2,
|
||||
HW_TOD_WR_TRIG_SEL_IRIGB_PPS = 3,
|
||||
HW_TOD_WR_TRIG_SEL_PWM_PPS = 4,
|
||||
HW_TOD_WR_TRIG_SEL_GPIO = 5,
|
||||
HW_TOD_WR_TRIG_SEL_FOD_SYNC = 6,
|
||||
WR_TRIG_SEL_MAX = HW_TOD_WR_TRIG_SEL_FOD_SYNC,
|
||||
};
|
||||
|
||||
enum scsr_read_trig_sel {
|
||||
/* CANCEL CURRENT TOD READ; MODULE BECOMES IDLE - NO TRIGGER OCCURS */
|
||||
SCSR_TOD_READ_TRIG_SEL_DISABLE = 0,
|
||||
/* TRIGGER IMMEDIATELY */
|
||||
SCSR_TOD_READ_TRIG_SEL_IMMEDIATE = 1,
|
||||
/* TRIGGER ON RISING EDGE OF INTERNAL TOD PPS SIGNAL */
|
||||
SCSR_TOD_READ_TRIG_SEL_TODPPS = 2,
|
||||
/* TRGGER ON RISING EDGE OF SELECTED REFERENCE INPUT */
|
||||
SCSR_TOD_READ_TRIG_SEL_REFCLK = 3,
|
||||
/* TRIGGER ON RISING EDGE OF SELECTED PWM DECODER 1PPS OUTPUT */
|
||||
SCSR_TOD_READ_TRIG_SEL_PWMPPS = 4,
|
||||
SCSR_TOD_READ_TRIG_SEL_RESERVED = 5,
|
||||
/* TRIGGER WHEN WRITE FREQUENCY EVENT OCCURS */
|
||||
SCSR_TOD_READ_TRIG_SEL_WRITEFREQUENCYEVENT = 6,
|
||||
/* TRIGGER ON SELECTED GPIO */
|
||||
SCSR_TOD_READ_TRIG_SEL_GPIO = 7,
|
||||
SCSR_TOD_READ_TRIG_SEL_MAX = SCSR_TOD_READ_TRIG_SEL_GPIO,
|
||||
};
|
||||
|
||||
/* Values STATUS.DPLL_SYS_STATUS.DPLL_SYS_STATE */
|
||||
enum dpll_state {
|
||||
DPLL_STATE_MIN = 0,
|
||||
DPLL_STATE_FREERUN = DPLL_STATE_MIN,
|
||||
DPLL_STATE_LOCKACQ = 1,
|
||||
DPLL_STATE_LOCKREC = 2,
|
||||
DPLL_STATE_LOCKED = 3,
|
||||
DPLL_STATE_HOLDOVER = 4,
|
||||
DPLL_STATE_OPEN_LOOP = 5,
|
||||
DPLL_STATE_MAX = DPLL_STATE_OPEN_LOOP,
|
||||
};
|
||||
|
||||
/* 4.8.7 only */
|
||||
enum scsr_tod_write_trig_sel {
|
||||
SCSR_TOD_WR_TRIG_SEL_DISABLE = 0,
|
||||
SCSR_TOD_WR_TRIG_SEL_IMMEDIATE = 1,
|
||||
SCSR_TOD_WR_TRIG_SEL_REFCLK = 2,
|
||||
SCSR_TOD_WR_TRIG_SEL_PWMPPS = 3,
|
||||
SCSR_TOD_WR_TRIG_SEL_TODPPS = 4,
|
||||
SCSR_TOD_WR_TRIG_SEL_SYNCFOD = 5,
|
||||
SCSR_TOD_WR_TRIG_SEL_GPIO = 6,
|
||||
SCSR_TOD_WR_TRIG_SEL_MAX = SCSR_TOD_WR_TRIG_SEL_GPIO,
|
||||
};
|
||||
|
||||
/* 4.8.7 only */
|
||||
enum scsr_tod_write_type_sel {
|
||||
SCSR_TOD_WR_TYPE_SEL_ABSOLUTE = 0,
|
||||
SCSR_TOD_WR_TYPE_SEL_DELTA_PLUS = 1,
|
||||
SCSR_TOD_WR_TYPE_SEL_DELTA_MINUS = 2,
|
||||
SCSR_TOD_WR_TYPE_SEL_MAX = SCSR_TOD_WR_TYPE_SEL_DELTA_MINUS,
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Core interface for Renesas Synchronization Management Unit (SMU) devices.
|
||||
*
|
||||
* Copyright (C) 2021 Integrated Device Technology, Inc., a Renesas Company.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_MFD_RSMU_H
|
||||
#define __LINUX_MFD_RSMU_H
|
||||
|
||||
/* The supported devices are ClockMatrix, Sabre and SnowLotus */
|
||||
enum rsmu_type {
|
||||
RSMU_CM = 0x34000,
|
||||
RSMU_SABRE = 0x33810,
|
||||
RSMU_SL = 0x19850,
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* struct rsmu_ddata - device data structure for sub devices.
|
||||
*
|
||||
* @dev: i2c/spi device.
|
||||
* @regmap: i2c/spi bus access.
|
||||
* @lock: mutex used by sub devices to make sure a series of
|
||||
* bus access requests are not interrupted.
|
||||
* @type: RSMU device type.
|
||||
* @page: i2c/spi bus driver internal use only.
|
||||
*/
|
||||
struct rsmu_ddata {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct mutex lock;
|
||||
enum rsmu_type type;
|
||||
u16 page;
|
||||
};
|
||||
#endif /* __LINUX_MFD_RSMU_H */
|
||||
+1
-1
@@ -896,7 +896,7 @@ static inline int of_parse_phandle_with_fixed_args(const struct device_node *np,
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int of_count_phandle_with_args(struct device_node *np,
|
||||
static inline int of_count_phandle_with_args(const struct device_node *np,
|
||||
const char *list_name,
|
||||
const char *cells_name)
|
||||
{
|
||||
|
||||
@@ -49,7 +49,7 @@ static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc)
|
||||
return container_of(gc, struct of_mm_gpio_chip, gc);
|
||||
}
|
||||
|
||||
extern int of_get_named_gpio_flags(struct device_node *np,
|
||||
extern int of_get_named_gpio_flags(const struct device_node *np,
|
||||
const char *list_name, int index, enum of_gpio_flags *flags);
|
||||
|
||||
extern int of_mm_gpiochip_add_data(struct device_node *np,
|
||||
@@ -67,7 +67,7 @@ extern void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc);
|
||||
#include <linux/errno.h>
|
||||
|
||||
/* Drivers may not strictly depend on the GPIO support, so let them link. */
|
||||
static inline int of_get_named_gpio_flags(struct device_node *np,
|
||||
static inline int of_get_named_gpio_flags(const struct device_node *np,
|
||||
const char *list_name, int index, enum of_gpio_flags *flags)
|
||||
{
|
||||
if (flags)
|
||||
@@ -98,7 +98,8 @@ static inline int of_get_named_gpio_flags(struct device_node *np,
|
||||
* The above example defines four GPIOs, two of which are not specified.
|
||||
* This function will return '4'
|
||||
*/
|
||||
static inline int of_gpio_named_count(struct device_node *np, const char* propname)
|
||||
static inline int of_gpio_named_count(const struct device_node *np,
|
||||
const char *propname)
|
||||
{
|
||||
return of_count_phandle_with_args(np, propname, "#gpio-cells");
|
||||
}
|
||||
@@ -109,12 +110,12 @@ static inline int of_gpio_named_count(struct device_node *np, const char* propna
|
||||
*
|
||||
* Same as of_gpio_named_count, but hard coded to use the 'gpios' property
|
||||
*/
|
||||
static inline int of_gpio_count(struct device_node *np)
|
||||
static inline int of_gpio_count(const struct device_node *np)
|
||||
{
|
||||
return of_gpio_named_count(np, "gpios");
|
||||
}
|
||||
|
||||
static inline int of_get_gpio_flags(struct device_node *np, int index,
|
||||
static inline int of_get_gpio_flags(const struct device_node *np, int index,
|
||||
enum of_gpio_flags *flags)
|
||||
{
|
||||
return of_get_named_gpio_flags(np, "gpios", index, flags);
|
||||
@@ -129,7 +130,7 @@ static inline int of_get_gpio_flags(struct device_node *np, int index,
|
||||
* Returns GPIO number to use with Linux generic GPIO API, or one of the errno
|
||||
* value on the error condition.
|
||||
*/
|
||||
static inline int of_get_named_gpio(struct device_node *np,
|
||||
static inline int of_get_named_gpio(const struct device_node *np,
|
||||
const char *propname, int index)
|
||||
{
|
||||
return of_get_named_gpio_flags(np, propname, index, NULL);
|
||||
@@ -143,7 +144,7 @@ static inline int of_get_named_gpio(struct device_node *np,
|
||||
* Returns GPIO number to use with Linux generic GPIO API, or one of the errno
|
||||
* value on the error condition.
|
||||
*/
|
||||
static inline int of_get_gpio(struct device_node *np, int index)
|
||||
static inline int of_get_gpio(const struct device_node *np, int index)
|
||||
{
|
||||
return of_get_gpio_flags(np, index, NULL);
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright(c) 2014 Intel Corporation.
|
||||
*/
|
||||
|
||||
#ifndef GPIO_DW_APB_H
|
||||
#define GPIO_DW_APB_H
|
||||
|
||||
#define DWAPB_MAX_GPIOS 32
|
||||
|
||||
struct dwapb_port_property {
|
||||
struct fwnode_handle *fwnode;
|
||||
unsigned int idx;
|
||||
unsigned int ngpio;
|
||||
unsigned int gpio_base;
|
||||
int irq[DWAPB_MAX_GPIOS];
|
||||
bool irq_shared;
|
||||
};
|
||||
|
||||
struct dwapb_platform_data {
|
||||
struct dwapb_port_property *properties;
|
||||
unsigned int nports;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -2,7 +2,7 @@
|
||||
#ifndef LINUX_SPI_MAX7301_H
|
||||
#define LINUX_SPI_MAX7301_H
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
|
||||
/*
|
||||
* Some registers must be read back to modify.
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
|
||||
#ifndef _LINUX_VIRTIO_GPIO_H
|
||||
#define _LINUX_VIRTIO_GPIO_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* Virtio GPIO request types */
|
||||
#define VIRTIO_GPIO_MSG_GET_NAMES 0x0001
|
||||
#define VIRTIO_GPIO_MSG_GET_DIRECTION 0x0002
|
||||
#define VIRTIO_GPIO_MSG_SET_DIRECTION 0x0003
|
||||
#define VIRTIO_GPIO_MSG_GET_VALUE 0x0004
|
||||
#define VIRTIO_GPIO_MSG_SET_VALUE 0x0005
|
||||
|
||||
/* Possible values of the status field */
|
||||
#define VIRTIO_GPIO_STATUS_OK 0x0
|
||||
#define VIRTIO_GPIO_STATUS_ERR 0x1
|
||||
|
||||
/* Direction types */
|
||||
#define VIRTIO_GPIO_DIRECTION_NONE 0x00
|
||||
#define VIRTIO_GPIO_DIRECTION_OUT 0x01
|
||||
#define VIRTIO_GPIO_DIRECTION_IN 0x02
|
||||
|
||||
struct virtio_gpio_config {
|
||||
__le16 ngpio;
|
||||
__u8 padding[2];
|
||||
__le32 gpio_names_size;
|
||||
} __packed;
|
||||
|
||||
/* Virtio GPIO Request / Response */
|
||||
struct virtio_gpio_request {
|
||||
__le16 type;
|
||||
__le16 gpio;
|
||||
__le32 value;
|
||||
};
|
||||
|
||||
struct virtio_gpio_response {
|
||||
__u8 status;
|
||||
__u8 value;
|
||||
};
|
||||
|
||||
struct virtio_gpio_response_get_names {
|
||||
__u8 status;
|
||||
__u8 value[];
|
||||
};
|
||||
|
||||
#endif /* _LINUX_VIRTIO_GPIO_H */
|
||||
@@ -58,6 +58,7 @@
|
||||
#define VIRTIO_ID_SCMI 32 /* virtio SCMI */
|
||||
#define VIRTIO_ID_I2C_ADAPTER 34 /* virtio i2c adapter */
|
||||
#define VIRTIO_ID_BT 40 /* virtio bluetooth */
|
||||
#define VIRTIO_ID_GPIO 41 /* virtio gpio */
|
||||
|
||||
/*
|
||||
* Virtio Transitional IDs
|
||||
|
||||
Reference in New Issue
Block a user