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:
Greg Kroah-Hartman
2021-09-14 18:50:17 +02:00
67 changed files with 2741 additions and 613 deletions
@@ -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;
};
};
};
+9 -1
View File
@@ -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.
+4 -7
View File
@@ -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
View File
@@ -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
+2 -1
View File
@@ -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:
+1 -1
View File
@@ -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,
};
+9 -6
View File
@@ -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
+1 -1
View File
@@ -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
+110 -68
View File
@@ -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;
+1 -44
View File
@@ -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
View File
@@ -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)
-112
View File
@@ -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, &reg, &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, &reg, &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
View File
@@ -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
View File
@@ -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);
+5 -8
View File
@@ -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;
}
+1
View File
@@ -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;
+2 -2
View File
@@ -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);
+24 -6
View File
@@ -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,
};
+3 -11
View File
@@ -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 = {
+374
View File
@@ -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");
+1 -1
View File
@@ -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)
+8 -8
View File
@@ -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
View File
@@ -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);
+28
View File
@@ -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
+5
View File
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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"),
};
+18
View File
@@ -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 },
+11 -1
View File
@@ -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);
+37 -34
View File
@@ -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);
}
+1
View File
@@ -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",
+2 -2
View File
@@ -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)
+4 -4
View File
@@ -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[] = {
+16
View File
@@ -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 */
+88
View File
@@ -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");
+203
View File
@@ -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");
+273
View File
@@ -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");
+33 -8
View File
@@ -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 = &regmap_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[] = {
+32
View File
@@ -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
View File
@@ -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);
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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);
+2 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+1 -1
View File
@@ -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;
}
+55 -20
View File
@@ -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);
+28 -26
View File
@@ -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);
+6 -8
View File
@@ -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)
{
+4
View File
@@ -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;
+2 -1
View File
@@ -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 */
+112
View File
@@ -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
+729
View File
@@ -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
+36
View File
@@ -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
View File
@@ -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)
{
+8 -7
View File
@@ -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);
}
-25
View File
@@ -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
+1 -1
View File
@@ -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.
+47
View File
@@ -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 */
+1
View File
@@ -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