Commit 532c2b92 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull MFD updates from Lee Jones:
 "New Drivers:
   - Add Cirrus Logic Madera Codec (CS47L35, CS47L85 and CS47L90/91) driver
   - Add ChromeOS EC CEC driver
   - Add ROHM BD71837 PMIC driver

  New Device Support:
   - Add support for Dialog Semi DA9063L PMIC variant to DA9063
   - Add support for Intel Ice Lake to Intel-PLSS-PCI
   - Add support for X-Powers AXP806 to AXP20x

  New Functionality:
   - Add support for USB Charging to the ChromeOS Embedded Controller
   - Add support for HDMI CEC to the ChromeOS Embedded Controller
   - Add support for HDMI CEC to Intel HDMI
   - Add support for accessory detection to Madera devices
   - Allow individual pins to be configured via DT' wlf,csnaddr-pd
   - Provide legacy platform specific EEPROM/Watchdog commands; rave-sp

  Fix-upsL
   - Trivial renaming/spelling fixes; cros_ec, da9063-*
   - Convert to Managed Resources (devm_*); da9063-*, ti_am335x_tscadc
   - Transition to helper macros/functions; da9063-*
   - Constify; kempld-core
   - Improve error path/messages; wm8994-core
   - Disable IRQs locally instead of relying on USB subsystem; dln2
   - Remove unused code; rave-sp
   - New exports; sec-core

  Bug Fixes:
   - Fix possible false I2C transaction error; arizona-core
   - Fix declared memory area size; hi655x-pmic
   - Fix checksum type; rave-sp
   - Fix incorrect default serial port configuration: rave-sp
   - Fix incorrect coherent DMA mask for sub-devices; sm501"

* tag 'mfd-next-4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (60 commits)
  mfd: madera: Add register definitions for accessory detect
  mfd: sm501: Set coherent_dma_mask when creating subdevices
  mfd: bd71837: Devicetree bindings for ROHM BD71837 PMIC
  mfd: bd71837: Core driver for ROHM BD71837 PMIC
  media: platform: cros-ec-cec: Fix dependency on MFD_CROS_EC
  mfd: sec-core: Export OF module alias table
  mfd: as3722: Disable auto-power-on when AC OK
  mfd: axp20x: Support AXP806 in I2C mode
  mfd: axp20x: Add self-working mode support for AXP806
  dt-bindings: mfd: axp20x: Add "self-working" mode for AXP806
  mfd: wm8994: Allow to configure CS/ADDR Pulldown from dts
  mfd: wm8994: Allow to configure Speaker Mode Pullup from dts
  mfd: rave-sp: Emulate CMD_GET_STATUS on device that don't support it
  mfd: rave-sp: Add legacy watchdog ping command translation
  mfd: rave-sp: Add legacy EEPROM access command translation
  mfd: rave-sp: Initialize flow control and parity of the port
  mfd: rave-sp: Fix incorrectly specified checksum type
  mfd: rave-sp: Remove unused defines
  mfd: hi655x: Fix regmap area declared size for hi655x
  mfd: ti_am335x_tscadc: Fix struct clk memory leak
  ...
parents 8786583d d2c9281c
...@@ -20,6 +20,8 @@ Optional properties: ...@@ -20,6 +20,8 @@ Optional properties:
- ams,enable-internal-i2c-pullup: Boolean property, to enable internal pullup on - ams,enable-internal-i2c-pullup: Boolean property, to enable internal pullup on
i2c scl/sda pins. Missing this will disable internal pullup on i2c i2c scl/sda pins. Missing this will disable internal pullup on i2c
scl/sda lines. scl/sda lines.
- ams,enable-ac-ok-power-on: Boolean property, to enable exit out of power off
mode with AC_OK pin (pin enabled in power off mode).
Optional submodule and their properties: Optional submodule and their properties:
======================================= =======================================
......
...@@ -44,8 +44,11 @@ Optional properties: ...@@ -44,8 +44,11 @@ Optional properties:
board is driving OTG VBus or not. board is driving OTG VBus or not.
(axp221 / axp223 / axp803/ axp813 only) (axp221 / axp223 / axp803/ axp813 only)
- x-powers,master-mode: Boolean (axp806 only). Set this when the PMIC is - x-powers,self-working-mode and
wired for master mode. The default is slave mode. x-powers,master-mode: Boolean (axp806 only). Set either of these when the
PMIC is wired for self-working mode or master mode.
If neither is set then slave mode is assumed.
This corresponds to how the MODESET pin is wired.
- <input>-supply: a phandle to the regulator supply node. May be omitted if - <input>-supply: a phandle to the regulator supply node. May be omitted if
inputs are unregulated, such as using the IPSOUT output inputs are unregulated, such as using the IPSOUT output
......
Cirrus Logic Madera class audio codecs Multi-Functional Device
These devices are audio SoCs with extensive digital capabilities and a range
of analogue I/O.
See also the child driver bindings in:
bindings/pinctrl/cirrus,madera-pinctrl.txt
bindings/regulator/arizona-regulator.txt
bindings/sound/madera.txt
Required properties:
- compatible : One of the following chip-specific strings:
"cirrus,cs47l35"
"cirrus,cs47l85"
"cirrus,cs47l90"
"cirrus,cs47l91"
"cirrus,wm1840"
- reg : I2C slave address when connected using I2C, chip select number when
using SPI.
- DCVDD-supply : Power supply for the device as defined in
bindings/regulator/regulator.txt
Mandatory on CS47L35, CS47L90, CS47L91
Optional on CS47L85, WM1840
- AVDD-supply, DBVDD1-supply, DBVDD2-supply, CPVDD1-supply, CPVDD2-supply :
Power supplies for the device
- DBVDD3-supply, DBVDD4-supply : Power supplies for the device
(CS47L85, CS47L90, CS47L91, WM1840)
- SPKVDDL-supply, SPKVDDR-supply : Power supplies for the device
(CS47L85, WM1840)
- SPKVDD-supply : Power supply for the device
(CS47L35)
- interrupt-controller : Indicates that this device is an interrupt controller
- #interrupt-cells: the number of cells to describe an IRQ, must be 2.
The first cell is the IRQ number.
The second cell is the flags, encoded as the trigger masks from
bindings/interrupt-controller/interrupts.txt
- gpio-controller : Indicates this device is a GPIO controller.
- #gpio-cells : Must be 2. The first cell is the pin number. The second cell
is reserved for future use and must be zero
- interrupt-parent : The parent interrupt controller.
- interrupts : The interrupt line the /IRQ signal for the device is
connected to.
Optional properties:
- MICVDD-supply : Power supply, only need to be specified if
powered externally
- reset-gpios : One entry specifying the GPIO controlling /RESET.
As defined in bindings/gpio.txt.
Although optional, it is strongly recommended to use a hardware reset
- MICBIASx : Initial data for the MICBIAS regulators, as covered in
Documentation/devicetree/bindings/regulator/regulator.txt.
One for each MICBIAS generator (MICBIAS1, MICBIAS2, ...)
(all codecs)
One for each output pin (MICBIAS1A, MIBCIAS1B, MICBIAS2A, ...)
(all except CS47L85, WM1840)
The following following additional property is supported for the generator
nodes:
- cirrus,ext-cap : Set to 1 if the MICBIAS has external decoupling
capacitors attached.
Optional child nodes:
micvdd : Node containing initialization data for the micvdd regulator
See bindings/regulator/arizona-regulator.txt
ldo1 : Node containing initialization data for the LDO1 regulator
See bindings/regulator/arizona-regulator.txt
(cs47l85, wm1840)
Example:
cs47l85@0 {
compatible = "cirrus,cs47l85";
reg = <0>;
reset-gpios = <&gpio 0>;
interrupt-controller;
#interrupt-cells = <2>;
interrupts = <&host_irq1>;
interrupt-parent = <&gic>;
gpio-controller;
#gpio-cells = <2>;
};
* ROHM BD71837 Power Management Integrated Circuit bindings
BD71837MWV is a programmable Power Management IC for powering single-core,
dual-core, and quad-core SoCs such as NXP-i.MX 8M. It is optimized for
low BOM cost and compact solution footprint. It integrates 8 Buck
egulators and 7 LDOs to provide all the power rails required by the SoC and
the commonly used peripherals.
Datasheet for PMIC is available at:
https://www.rohm.com/datasheet/BD71837MWV/bd71837mwv-e
Required properties:
- compatible : Should be "rohm,bd71837".
- reg : I2C slave address.
- interrupt-parent : Phandle to the parent interrupt controller.
- interrupts : The interrupt line the device is connected to.
- clocks : The parent clock connected to PMIC. If this is missing
32768 KHz clock is assumed.
- #clock-cells : Should be 0.
- regulators: : List of child nodes that specify the regulators.
Please see ../regulator/rohm,bd71837-regulator.txt
Optional properties:
- clock-output-names : Should contain name for output clock.
Example:
/* external oscillator node */
osc: oscillator {
compatible = "fixed-clock";
#clock-cells = <1>;
clock-frequency = <32768>;
clock-output-names = "osc";
};
pmic: pmic@4b {
compatible = "rohm,bd71837";
reg = <0x4b>;
interrupt-parent = <&gpio1>;
interrupts = <29 GPIO_ACTIVE_LOW>;
interrupt-names = "irq";
#clock-cells = <0>;
clocks = <&osc 0>;
clock-output-names = "bd71837-32k-out";
regulators {
buck1: BUCK1 {
regulator-name = "buck1";
regulator-min-microvolt = <700000>;
regulator-max-microvolt = <1300000>;
regulator-boot-on;
regulator-ramp-delay = <1250>;
};
};
};
/* Clock consumer node */
rtc@0 {
compatible = "company,my-rtc";
clock-names = "my-clock";
clocks = <&pmic>;
};
...@@ -22,7 +22,7 @@ Required properties: ...@@ -22,7 +22,7 @@ Required properties:
The valid regulator-compatible values are: The valid regulator-compatible values are:
tps65910: vrtc, vio, vdd1, vdd2, vdd3, vdig1, vdig2, vpll, vdac, vaux1, tps65910: vrtc, vio, vdd1, vdd2, vdd3, vdig1, vdig2, vpll, vdac, vaux1,
vaux2, vaux33, vmmc, vbb vaux2, vaux33, vmmc, vbb
tps65911: vrtc, vio, vdd1, vdd3, vddctrl, ldo1, ldo2, ldo3, ldo4, ldo5, tps65911: vrtc, vio, vdd1, vdd2, vddctrl, ldo1, ldo2, ldo3, ldo4, ldo5,
ldo6, ldo7, ldo8 ldo6, ldo7, ldo8
- xxx-supply: Input voltage supply regulator. - xxx-supply: Input voltage supply regulator.
......
Cirrus Logic Madera class audio codecs pinctrl driver
The Cirrus Logic Madera codecs provide a number of GPIO functions for
interfacing to external hardware and to provide logic outputs to other devices.
Certain groups of GPIO pins also have an alternate function, normally as an
audio interface.
The set of available GPIOs, functions and alternate function groups differs
between codecs so refer to the datasheet for the codec for further information
on what is supported on that device.
The properties for this driver exist within the parent MFD driver node.
See also
the core bindings for the parent MFD driver:
Documentation/devicetree/bindings/mfd/madera.txt
the generic pinmix bindings:
Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
Required properties of parent mfd node:
- pinctrl-names : must be "default"
- pinctrl-0 : a phandle to the node containing the subnodes containing default
configurations
Required subnodes:
One subnode is required to contain the default settings. It contains an
arbitrary number of configuration subnodes, one for each group or pin
configuration you want to apply as a default.
Required properties of configuration subnodes:
- groups : name of one pin group to configure. One of:
aif1, aif2, aif3, aif4, mif1, mif2, mif3, pdmspk1, pdmspk2,
dmic4, dmic5, dmic6,
gpio1, gpio2, ..., gpio40
The gpioN groups select the single pin of this name for configuration
Optional properties of configuration subnodes:
Any configuration option not explicitly listed in the dts will be left at
chip default setting.
- function : name of function to assign to this group. One of:
aif1, aif2, aif3, aif4, mif1, mif2, mif3, pdmspk1, pdmspk2,
dmic3, dmic4, dmic5, dmic6,
io, dsp-gpio, irq1, irq2,
fll1-clk, fll1-lock, fll2-clk, fll2-lock, fll3-clk, fll3-lock,
fllao-clk, fllao-lock,
opclk, opclk-async, pwm1, pwm2, spdif,
asrc1-in1-lock, asrc1-in2-lock, asrc2-in1-lock, asrc2-in2-lock,
spkl-short-circuit, spkr-short-circuit, spk-shutdown,
spk-overheat-shutdown, spk-overheat-warn,
timer1-sts, timer2-sts, timer3-sts, timer4-sts, timer5-sts, timer6-sts,
timer7-sts, timer8-sts,
log1-fifo-ne, log2-fifo-ne, log3-fifo-ne, log4-fifo-ne, log5-fifo-ne,
log6-fifo-ne, log7-fifo-ne, log8-fifo-ne,
- bias-disable : disable pull-up and pull-down
- bias-bus-hold : enable buskeeper
- bias-pull-up : output is pulled-up
- bias-pull-down : output is pulled-down
- drive-push-pull : CMOS output
- drive-open-drain : open-drain output
- drive-strength : drive strength in mA. Valid values are 4 or 8
- input-schmitt-enable : enable schmitt-trigger mode
- input-schmitt-disable : disable schmitt-trigger mode
- input-debounce : A value of 0 disables debounce, a value !=0 enables
debounce
- output-low : set the pin to output mode with low level
- output-high : set the pin to output mode with high level
Example:
cs47l85@0 {
compatible = "cirrus,cs47l85";
pinctrl-names = "default";
pinctrl-0 = <&cs47l85_defaults>;
cs47l85_defaults: cs47l85-gpio-defaults {
aif1 {
groups = "aif1";
function = "aif1";
bias-bus-hold;
};
aif2 {
groups = "aif2";
function = "aif2";
bias-bus-hold;
};
opclk {
groups = "gpio1";
function = "opclk";
bias-pull-up;
drive-strength = <8>;
};
};
};
...@@ -3562,6 +3562,22 @@ M: Christian Benvenuti <benve@cisco.com> ...@@ -3562,6 +3562,22 @@ M: Christian Benvenuti <benve@cisco.com>
S: Supported S: Supported
F: drivers/infiniband/hw/usnic/ F: drivers/infiniband/hw/usnic/
CIRRUS LOGIC MADERA CODEC DRIVERS
M: Charles Keepax <ckeepax@opensource.cirrus.com>
M: Richard Fitzgerald <rf@opensource.cirrus.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
L: patches@opensource.cirrus.com
T: git https://github.com/CirrusLogic/linux-drivers.git
W: https://github.com/CirrusLogic/linux-drivers/wiki
S: Supported
F: Documentation/devicetree/bindings/mfd/madera.txt
F: Documentation/devicetree/bindings/pinctrl/cirrus,madera-pinctrl.txt
F: include/linux/mfd/madera/*
F: drivers/gpio/gpio-madera*
F: drivers/mfd/madera*
F: drivers/mfd/cs47l*
F: drivers/pinctrl/cirrus/*
CLANG-FORMAT FILE CLANG-FORMAT FILE
M: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> M: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
S: Maintained S: Maintained
......
...@@ -155,8 +155,8 @@ CONFIG_THERMAL_EMULATION=y ...@@ -155,8 +155,8 @@ CONFIG_THERMAL_EMULATION=y
CONFIG_WATCHDOG=y CONFIG_WATCHDOG=y
CONFIG_S3C2410_WATCHDOG=y CONFIG_S3C2410_WATCHDOG=y
CONFIG_MFD_CROS_EC=y CONFIG_MFD_CROS_EC=y
CONFIG_MFD_CROS_EC_I2C=y CONFIG_CROS_EC_I2C=y
CONFIG_MFD_CROS_EC_SPI=y CONFIG_CROS_EC_SPI=y
CONFIG_MFD_MAX14577=y CONFIG_MFD_MAX14577=y
CONFIG_MFD_MAX77686=y CONFIG_MFD_MAX77686=y
CONFIG_MFD_MAX77693=y CONFIG_MFD_MAX77693=y
......
...@@ -490,8 +490,8 @@ CONFIG_MFD_AC100=y ...@@ -490,8 +490,8 @@ CONFIG_MFD_AC100=y
CONFIG_MFD_AXP20X_I2C=y CONFIG_MFD_AXP20X_I2C=y
CONFIG_MFD_AXP20X_RSB=y CONFIG_MFD_AXP20X_RSB=y
CONFIG_MFD_CROS_EC=m CONFIG_MFD_CROS_EC=m
CONFIG_MFD_CROS_EC_I2C=m CONFIG_CROS_EC_I2C=m
CONFIG_MFD_CROS_EC_SPI=m CONFIG_CROS_EC_SPI=m
CONFIG_MFD_DA9063=m CONFIG_MFD_DA9063=m
CONFIG_MFD_MAX14577=y CONFIG_MFD_MAX14577=y
CONFIG_MFD_MAX77686=y CONFIG_MFD_MAX77686=y
......
...@@ -398,8 +398,8 @@ CONFIG_MFD_AS3711=y ...@@ -398,8 +398,8 @@ CONFIG_MFD_AS3711=y
CONFIG_MFD_BCM590XX=m CONFIG_MFD_BCM590XX=m
CONFIG_MFD_AXP20X=y CONFIG_MFD_AXP20X=y
CONFIG_MFD_CROS_EC=m CONFIG_MFD_CROS_EC=m
CONFIG_MFD_CROS_EC_I2C=m CONFIG_CROS_EC_I2C=m
CONFIG_MFD_CROS_EC_SPI=m CONFIG_CROS_EC_SPI=m
CONFIG_MFD_ASIC3=y CONFIG_MFD_ASIC3=y
CONFIG_PMIC_DA903X=y CONFIG_PMIC_DA903X=y
CONFIG_HTC_EGPIO=y CONFIG_HTC_EGPIO=y
......
...@@ -373,8 +373,8 @@ CONFIG_UNIPHIER_WATCHDOG=y ...@@ -373,8 +373,8 @@ CONFIG_UNIPHIER_WATCHDOG=y
CONFIG_BCM2835_WDT=y CONFIG_BCM2835_WDT=y
CONFIG_MFD_AXP20X_RSB=y CONFIG_MFD_AXP20X_RSB=y
CONFIG_MFD_CROS_EC=y CONFIG_MFD_CROS_EC=y
CONFIG_MFD_CROS_EC_I2C=y CONFIG_CROS_EC_I2C=y
CONFIG_MFD_CROS_EC_SPI=y CONFIG_CROS_EC_SPI=y
CONFIG_MFD_CROS_EC_CHARDEV=m CONFIG_MFD_CROS_EC_CHARDEV=m
CONFIG_MFD_EXYNOS_LPASS=m CONFIG_MFD_EXYNOS_LPASS=m
CONFIG_MFD_HI6421_PMIC=y CONFIG_MFD_HI6421_PMIC=y
......
...@@ -1049,6 +1049,12 @@ config GPIO_LP87565 ...@@ -1049,6 +1049,12 @@ config GPIO_LP87565
This driver can also be built as a module. If so, the module will be This driver can also be built as a module. If so, the module will be
called gpio-lp87565. called gpio-lp87565.
config GPIO_MADERA
tristate "Cirrus Logic Madera class codecs"
depends on PINCTRL_MADERA
help
Support for GPIOs on Cirrus Logic Madera class codecs.
config GPIO_MAX77620 config GPIO_MAX77620
tristate "GPIO support for PMIC MAX77620 and MAX20024" tristate "GPIO support for PMIC MAX77620 and MAX20024"
depends on MFD_MAX77620 depends on MFD_MAX77620
......
...@@ -71,6 +71,7 @@ obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o ...@@ -71,6 +71,7 @@ obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o
obj-$(CONFIG_GPIO_LP873X) += gpio-lp873x.o obj-$(CONFIG_GPIO_LP873X) += gpio-lp873x.o
obj-$(CONFIG_GPIO_LP87565) += gpio-lp87565.o obj-$(CONFIG_GPIO_LP87565) += gpio-lp87565.o
obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o
obj-$(CONFIG_GPIO_MADERA) += gpio-madera.o
obj-$(CONFIG_GPIO_MAX3191X) += gpio-max3191x.o obj-$(CONFIG_GPIO_MAX3191X) += gpio-max3191x.o
obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o
obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o
......
// SPDX-License-Identifier: GPL-2.0
/*
* GPIO support for Cirrus Logic Madera codecs
*
* Copyright (C) 2015-2018 Cirrus Logic
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; version 2.
*/
#include <linux/gpio/driver.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mfd/madera/core.h>
#include <linux/mfd/madera/pdata.h>
#include <linux/mfd/madera/registers.h>
struct madera_gpio {
struct madera *madera;
/* storage space for the gpio_chip we're using */
struct gpio_chip gpio_chip;
};
static int madera_gpio_get_direction(struct gpio_chip *chip,
unsigned int offset)
{
struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
struct madera *madera = madera_gpio->madera;
unsigned int reg_offset = 2 * offset;
unsigned int val;
int ret;
ret = regmap_read(madera->regmap, MADERA_GPIO1_CTRL_2 + reg_offset,
&val);
if (ret < 0)
return ret;
return !!(val & MADERA_GP1_DIR_MASK);
}
static int madera_gpio_direction_in(struct gpio_chip *chip, unsigned int offset)
{
struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
struct madera *madera = madera_gpio->madera;
unsigned int reg_offset = 2 * offset;
return regmap_update_bits(madera->regmap,
MADERA_GPIO1_CTRL_2 + reg_offset,
MADERA_GP1_DIR_MASK, MADERA_GP1_DIR);
}
static int madera_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
struct madera *madera = madera_gpio->madera;
unsigned int reg_offset = 2 * offset;
unsigned int val;
int ret;
ret = regmap_read(madera->regmap, MADERA_GPIO1_CTRL_1 + reg_offset,
&val);
if (ret < 0)
return ret;
return !!(val & MADERA_GP1_LVL_MASK);
}
static int madera_gpio_direction_out(struct gpio_chip *chip,
unsigned int offset, int value)
{
struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
struct madera *madera = madera_gpio->madera;
unsigned int reg_offset = 2 * offset;
unsigned int reg_val = value ? MADERA_GP1_LVL : 0;
int ret;
ret = regmap_update_bits(madera->regmap,
MADERA_GPIO1_CTRL_2 + reg_offset,
MADERA_GP1_DIR_MASK, 0);
if (ret < 0)
return ret;
return regmap_update_bits(madera->regmap,
MADERA_GPIO1_CTRL_1 + reg_offset,
MADERA_GP1_LVL_MASK, reg_val);
}
static void madera_gpio_set(struct gpio_chip *chip, unsigned int offset,
int value)
{
struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
struct madera *madera = madera_gpio->madera;
unsigned int reg_offset = 2 * offset;
unsigned int reg_val = value ? MADERA_GP1_LVL : 0;
int ret;
ret = regmap_update_bits(madera->regmap,
MADERA_GPIO1_CTRL_1 + reg_offset,
MADERA_GP1_LVL_MASK, reg_val);
/* set() doesn't return an error so log a warning */
if (ret)
dev_warn(madera->dev, "Failed to write to 0x%x (%d)\n",
MADERA_GPIO1_CTRL_1 + reg_offset, ret);
}
static struct gpio_chip madera_gpio_chip = {
.label = "madera",
.owner = THIS_MODULE,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.get_direction = madera_gpio_get_direction,
.direction_input = madera_gpio_direction_in,
.get = madera_gpio_get,
.direction_output = madera_gpio_direction_out,
.set = madera_gpio_set,
.set_config = gpiochip_generic_config,
.can_sleep = true,
};
static int madera_gpio_probe(struct platform_device *pdev)
{
struct madera *madera = dev_get_drvdata(pdev->dev.parent);
struct madera_pdata *pdata = dev_get_platdata(madera->dev);
struct madera_gpio *madera_gpio;
int ret;
madera_gpio = devm_kzalloc(&pdev->dev, sizeof(*madera_gpio),
GFP_KERNEL);
if (!madera_gpio)
return -ENOMEM;
madera_gpio->madera = madera;
/* Construct suitable gpio_chip from the template in madera_gpio_chip */
madera_gpio->gpio_chip = madera_gpio_chip;
madera_gpio->gpio_chip.parent = pdev->dev.parent;
switch (madera->type) {
case CS47L35:
madera_gpio->gpio_chip.ngpio = CS47L35_NUM_GPIOS;
break;
case CS47L85:
case WM1840:
madera_gpio->gpio_chip.ngpio = CS47L85_NUM_GPIOS;
break;
case CS47L90:
case CS47L91:
madera_gpio->gpio_chip.ngpio = CS47L90_NUM_GPIOS;
break;
default:
dev_err(&pdev->dev, "Unknown chip variant %d\n", madera->type);
return -EINVAL;
}
/* We want to be usable on systems that don't use devicetree or acpi */
if (pdata && pdata->gpio_base)
madera_gpio->gpio_chip.base = pdata->gpio_base;
else
madera_gpio->gpio_chip.base = -1;
ret = devm_gpiochip_add_data(&pdev->dev,
&madera_gpio->gpio_chip,
madera_gpio);
if (ret < 0) {
dev_dbg(&pdev->dev, "Could not register gpiochip, %d\n", ret);
return ret;
}
/*
* This is part of a composite MFD device which can only be used with
* the corresponding pinctrl driver. On all supported silicon the GPIO
* to pinctrl mapping is fixed in the silicon, so we register it
* explicitly instead of requiring a redundant gpio-ranges in the
* devicetree.
* In any case we also want to work on systems that don't use devicetree
* or acpi.
*/
ret = gpiochip_add_pin_range(&madera_gpio->gpio_chip, "madera-pinctrl",
0, 0, madera_gpio->gpio_chip.ngpio);
if (ret) {
dev_dbg(&pdev->dev, "Failed to add pin range (%d)\n", ret);
return ret;
}
return 0;
}
static struct platform_driver madera_gpio_driver = {
.driver = {
.name = "madera-gpio",
},
.probe = madera_gpio_probe,
};
module_platform_driver(madera_gpio_driver);
MODULE_SOFTDEP("pre: pinctrl-madera");
MODULE_DESCRIPTION("GPIO interface for Madera codecs");
MODULE_AUTHOR("Nariman Poushin <nariman@opensource.cirrus.com>");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:madera-gpio");
...@@ -24,6 +24,7 @@ config DRM_I915 ...@@ -24,6 +24,7 @@ config DRM_I915
select IOSF_MBI select IOSF_MBI
select CRC32 select CRC32
select SND_HDA_I915 if SND_HDA_CORE select SND_HDA_I915 if SND_HDA_CORE
select CEC_CORE if CEC_NOTIFIER
help help
Choose this option if you have a system that has "Intel Graphics Choose this option if you have a system that has "Intel Graphics
Media Accelerator" or "HD Graphics" integrated graphics, Media Accelerator" or "HD Graphics" integrated graphics,
......
...@@ -126,6 +126,30 @@ enum port { ...@@ -126,6 +126,30 @@ enum port {
#define port_name(p) ((p) + 'A') #define port_name(p) ((p) + 'A')
/*
* Ports identifier referenced from other drivers.
* Expected to remain stable over time
*/
static inline const char *port_identifier(enum port port)
{
switch (port) {
case PORT_A:
return "Port A";
case PORT_B:
return "Port B";
case PORT_C:
return "Port C";
case PORT_D:
return "Port D";
case PORT_E:
return "Port E";
case PORT_F:
return "Port F";
default:
return "<invalid>";
}
}
enum tc_port { enum tc_port {
PORT_TC_NONE = -1, PORT_TC_NONE = -1,
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <drm/drm_dp_mst_helper.h> #include <drm/drm_dp_mst_helper.h>
#include <drm/drm_rect.h> #include <drm/drm_rect.h>
#include <drm/drm_atomic.h> #include <drm/drm_atomic.h>
#include <media/cec-notifier.h>
/** /**
* __wait_for - magic wait macro * __wait_for - magic wait macro
...@@ -1016,6 +1017,7 @@ struct intel_hdmi { ...@@ -1016,6 +1017,7 @@ struct intel_hdmi {
bool has_audio; bool has_audio;
bool rgb_quant_range_selectable; bool rgb_quant_range_selectable;
struct intel_connector *attached_connector; struct intel_connector *attached_connector;
struct cec_notifier *cec_notifier;
}; };
struct intel_dp_mst_encoder; struct intel_dp_mst_encoder;
......
...@@ -1899,6 +1899,8 @@ intel_hdmi_set_edid(struct drm_connector *connector) ...@@ -1899,6 +1899,8 @@ intel_hdmi_set_edid(struct drm_connector *connector)
connected = true; connected = true;
} }
cec_notifier_set_phys_addr_from_edid(intel_hdmi->cec_notifier, edid);
return connected; return connected;
} }
...@@ -1907,6 +1909,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) ...@@ -1907,6 +1909,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
{ {
enum drm_connector_status status; enum drm_connector_status status;
struct drm_i915_private *dev_priv = to_i915(connector->dev); struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name); connector->base.id, connector->name);
...@@ -1922,6 +1925,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) ...@@ -1922,6 +1925,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
if (status != connector_status_connected)
cec_notifier_phys_addr_invalidate(intel_hdmi->cec_notifier);
return status; return status;
} }
...@@ -2062,6 +2068,8 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder, ...@@ -2062,6 +2068,8 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder,
static void intel_hdmi_destroy(struct drm_connector *connector) static void intel_hdmi_destroy(struct drm_connector *connector)
{ {
if (intel_attached_hdmi(connector)->cec_notifier)
cec_notifier_put(intel_attached_hdmi(connector)->cec_notifier);
kfree(to_intel_connector(connector)->detect_edid); kfree(to_intel_connector(connector)->detect_edid);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
kfree(connector); kfree(connector);
...@@ -2382,6 +2390,11 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, ...@@ -2382,6 +2390,11 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
u32 temp = I915_READ(PEG_BAND_GAP_DATA); u32 temp = I915_READ(PEG_BAND_GAP_DATA);
I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
} }
intel_hdmi->cec_notifier = cec_notifier_get_conn(dev->dev,
port_identifier(port));
if (!intel_hdmi->cec_notifier)
DRM_DEBUG_KMS("CEC notifier get failed\n");
} }
void intel_hdmi_init(struct drm_i915_private *dev_priv, void intel_hdmi_init(struct drm_i915_private *dev_priv,
......
...@@ -721,7 +721,7 @@ config KEYBOARD_CROS_EC ...@@ -721,7 +721,7 @@ config KEYBOARD_CROS_EC
help help
Say Y here to enable the matrix keyboard used by ChromeOS devices Say Y here to enable the matrix keyboard used by ChromeOS devices
and implemented on the ChromeOS EC. You must enable one bus option and implemented on the ChromeOS EC. You must enable one bus option
(MFD_CROS_EC_I2C or MFD_CROS_EC_SPI) to use this. (CROS_EC_I2C or CROS_EC_SPI) to use this.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called cros_ec_keyb. module will be called cros_ec_keyb.
......
...@@ -21,6 +21,7 @@ struct cec_notifier { ...@@ -21,6 +21,7 @@ struct cec_notifier {
struct list_head head; struct list_head head;
struct kref kref; struct kref kref;
struct device *dev; struct device *dev;
const char *conn;
struct cec_adapter *cec_adap; struct cec_adapter *cec_adap;
void (*callback)(struct cec_adapter *adap, u16 pa); void (*callback)(struct cec_adapter *adap, u16 pa);
...@@ -30,13 +31,14 @@ struct cec_notifier { ...@@ -30,13 +31,14 @@ struct cec_notifier {
static LIST_HEAD(cec_notifiers); static LIST_HEAD(cec_notifiers);
static DEFINE_MUTEX(cec_notifiers_lock); static DEFINE_MUTEX(cec_notifiers_lock);
struct cec_notifier *cec_notifier_get(struct device *dev) struct cec_notifier *cec_notifier_get_conn(struct device *dev, const char *conn)
{ {
struct cec_notifier *n; struct cec_notifier *n;
mutex_lock(&cec_notifiers_lock); mutex_lock(&cec_notifiers_lock);
list_for_each_entry(n, &cec_notifiers, head) { list_for_each_entry(n, &cec_notifiers, head) {
if (n->dev == dev) { if (n->dev == dev &&
(!conn || !strcmp(n->conn, conn))) {
kref_get(&n->kref); kref_get(&n->kref);
mutex_unlock(&cec_notifiers_lock); mutex_unlock(&cec_notifiers_lock);
return n; return n;
...@@ -46,6 +48,8 @@ struct cec_notifier *cec_notifier_get(struct device *dev) ...@@ -46,6 +48,8 @@ struct cec_notifier *cec_notifier_get(struct device *dev)
if (!n) if (!n)
goto unlock; goto unlock;
n->dev = dev; n->dev = dev;
if (conn)
n->conn = kstrdup(conn, GFP_KERNEL);
n->phys_addr = CEC_PHYS_ADDR_INVALID; n->phys_addr = CEC_PHYS_ADDR_INVALID;
mutex_init(&n->lock); mutex_init(&n->lock);
kref_init(&n->kref); kref_init(&n->kref);
...@@ -54,7 +58,7 @@ struct cec_notifier *cec_notifier_get(struct device *dev) ...@@ -54,7 +58,7 @@ struct cec_notifier *cec_notifier_get(struct device *dev)
mutex_unlock(&cec_notifiers_lock); mutex_unlock(&cec_notifiers_lock);
return n; return n;
} }
EXPORT_SYMBOL_GPL(cec_notifier_get); EXPORT_SYMBOL_GPL(cec_notifier_get_conn);
static void cec_notifier_release(struct kref *kref) static void cec_notifier_release(struct kref *kref)
{ {
...@@ -62,6 +66,7 @@ static void cec_notifier_release(struct kref *kref) ...@@ -62,6 +66,7 @@ static void cec_notifier_release(struct kref *kref)
container_of(kref, struct cec_notifier, kref); container_of(kref, struct cec_notifier, kref);
list_del(&n->head); list_del(&n->head);
kfree(n->conn);
kfree(n); kfree(n);
} }
......
...@@ -536,6 +536,17 @@ menuconfig CEC_PLATFORM_DRIVERS ...@@ -536,6 +536,17 @@ menuconfig CEC_PLATFORM_DRIVERS
if CEC_PLATFORM_DRIVERS if CEC_PLATFORM_DRIVERS
config VIDEO_CROS_EC_CEC
tristate "ChromeOS EC CEC driver"
depends on MFD_CROS_EC
select CEC_CORE
select CEC_NOTIFIER
---help---
If you say yes here you will get support for the
ChromeOS Embedded Controller's CEC.
The CEC bus is present in the HDMI connector and enables communication
between compatible devices.
config VIDEO_MESON_AO_CEC config VIDEO_MESON_AO_CEC
tristate "Amlogic Meson AO CEC driver" tristate "Amlogic Meson AO CEC driver"
depends on ARCH_MESON || COMPILE_TEST depends on ARCH_MESON || COMPILE_TEST
......
...@@ -94,3 +94,5 @@ obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom/camss/ ...@@ -94,3 +94,5 @@ obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom/camss/
obj-$(CONFIG_VIDEO_QCOM_VENUS) += qcom/venus/ obj-$(CONFIG_VIDEO_QCOM_VENUS) += qcom/venus/
obj-y += meson/ obj-y += meson/
obj-y += cros-ec-cec/
obj-$(CONFIG_VIDEO_CROS_EC_CEC) += cros-ec-cec.o
// SPDX-License-Identifier: GPL-2.0+
/*
* CEC driver for ChromeOS Embedded Controller
*
* Copyright (c) 2018 BayLibre, SAS
* Author: Neil Armstrong <narmstrong@baylibre.com>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/dmi.h>
#include <linux/pci.h>
#include <linux/cec.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <media/cec.h>
#include <media/cec-notifier.h>
#include <linux/mfd/cros_ec.h>
#include <linux/mfd/cros_ec_commands.h>
#define DRV_NAME "cros-ec-cec"
/**
* struct cros_ec_cec - Driver data for EC CEC
*
* @cros_ec: Pointer to EC device
* @notifier: Notifier info for responding to EC events
* @adap: CEC adapter
* @notify: CEC notifier pointer
* @rx_msg: storage for a received message
*/
struct cros_ec_cec {
struct cros_ec_device *cros_ec;
struct notifier_block notifier;
struct cec_adapter *adap;
struct cec_notifier *notify;
struct cec_msg rx_msg;
};
static void handle_cec_message(struct cros_ec_cec *cros_ec_cec)
{
struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
uint8_t *cec_message = cros_ec->event_data.data.cec_message;
unsigned int len = cros_ec->event_size;
cros_ec_cec->rx_msg.len = len;
memcpy(cros_ec_cec->rx_msg.msg, cec_message, len);
cec_received_msg(cros_ec_cec->adap, &cros_ec_cec->rx_msg);
}
static void handle_cec_event(struct cros_ec_cec *cros_ec_cec)
{
struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
uint32_t events = cros_ec->event_data.data.cec_events;
if (events & EC_MKBP_CEC_SEND_OK)
cec_transmit_attempt_done(cros_ec_cec->adap,
CEC_TX_STATUS_OK);
/* FW takes care of all retries, tell core to avoid more retries */
if (events & EC_MKBP_CEC_SEND_FAILED)
cec_transmit_attempt_done(cros_ec_cec->adap,
CEC_TX_STATUS_MAX_RETRIES |
CEC_TX_STATUS_NACK);
}
static int cros_ec_cec_event(struct notifier_block *nb,
unsigned long queued_during_suspend,
void *_notify)
{
struct cros_ec_cec *cros_ec_cec;
struct cros_ec_device *cros_ec;
cros_ec_cec = container_of(nb, struct cros_ec_cec, notifier);
cros_ec = cros_ec_cec->cros_ec;
if (cros_ec->event_data.event_type == EC_MKBP_EVENT_CEC_EVENT) {
handle_cec_event(cros_ec_cec);
return NOTIFY_OK;
}
if (cros_ec->event_data.event_type == EC_MKBP_EVENT_CEC_MESSAGE) {
handle_cec_message(cros_ec_cec);
return NOTIFY_OK;
}
return NOTIFY_DONE;
}
static int cros_ec_cec_set_log_addr(struct cec_adapter *adap, u8 logical_addr)
{
struct cros_ec_cec *cros_ec_cec = adap->priv;
struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
struct {
struct cros_ec_command msg;
struct ec_params_cec_set data;
} __packed msg = {};
int ret;
msg.msg.command = EC_CMD_CEC_SET;
msg.msg.outsize = sizeof(msg.data);
msg.data.cmd = CEC_CMD_LOGICAL_ADDRESS;
msg.data.val = logical_addr;
ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
if (ret < 0) {
dev_err(cros_ec->dev,
"error setting CEC logical address on EC: %d\n", ret);
return ret;
}
return 0;
}
static int cros_ec_cec_transmit(struct cec_adapter *adap, u8 attempts,
u32 signal_free_time, struct cec_msg *cec_msg)
{
struct cros_ec_cec *cros_ec_cec = adap->priv;
struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
struct {
struct cros_ec_command msg;
struct ec_params_cec_write data;
} __packed msg = {};
int ret;
msg.msg.command = EC_CMD_CEC_WRITE_MSG;
msg.msg.outsize = cec_msg->len;
memcpy(msg.data.msg, cec_msg->msg, cec_msg->len);
ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
if (ret < 0) {
dev_err(cros_ec->dev,
"error writing CEC msg on EC: %d\n", ret);
return ret;
}
return 0;
}
static int cros_ec_cec_adap_enable(struct cec_adapter *adap, bool enable)
{
struct cros_ec_cec *cros_ec_cec = adap->priv;
struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
struct {
struct cros_ec_command msg;
struct ec_params_cec_set data;
} __packed msg = {};
int ret;
msg.msg.command = EC_CMD_CEC_SET;
msg.msg.outsize = sizeof(msg.data);
msg.data.cmd = CEC_CMD_ENABLE;
msg.data.val = enable;
ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
if (ret < 0) {
dev_err(cros_ec->dev,
"error %sabling CEC on EC: %d\n",
(enable ? "en" : "dis"), ret);
return ret;
}
return 0;
}
static const struct cec_adap_ops cros_ec_cec_ops = {
.adap_enable = cros_ec_cec_adap_enable,
.adap_log_addr = cros_ec_cec_set_log_addr,
.adap_transmit = cros_ec_cec_transmit,
};
#ifdef CONFIG_PM_SLEEP
static int cros_ec_cec_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct cros_ec_cec *cros_ec_cec = dev_get_drvdata(&pdev->dev);
if (device_may_wakeup(dev))
enable_irq_wake(cros_ec_cec->cros_ec->irq);
return 0;
}
static int cros_ec_cec_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct cros_ec_cec *cros_ec_cec = dev_get_drvdata(&pdev->dev);
if (device_may_wakeup(dev))
disable_irq_wake(cros_ec_cec->cros_ec->irq);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(cros_ec_cec_pm_ops,
cros_ec_cec_suspend, cros_ec_cec_resume);
#if IS_ENABLED(CONFIG_PCI) && IS_ENABLED(CONFIG_DMI)
/*
* The Firmware only handles a single CEC interface tied to a single HDMI
* connector we specify along with the DRM device name handling the HDMI output
*/
struct cec_dmi_match {
char *sys_vendor;
char *product_name;
char *devname;
char *conn;
};
static const struct cec_dmi_match cec_dmi_match_table[] = {
/* Google Fizz */
{ "Google", "Fizz", "0000:00:02.0", "Port B" },
};
static int cros_ec_cec_get_notifier(struct device *dev,
struct cec_notifier **notify)
{
int i;
for (i = 0 ; i < ARRAY_SIZE(cec_dmi_match_table) ; ++i) {
const struct cec_dmi_match *m = &cec_dmi_match_table[i];
if (dmi_match(DMI_SYS_VENDOR, m->sys_vendor) &&
dmi_match(DMI_PRODUCT_NAME, m->product_name)) {
struct device *d;
/* Find the device, bail out if not yet registered */
d = bus_find_device_by_name(&pci_bus_type, NULL,
m->devname);
if (!d)
return -EPROBE_DEFER;
*notify = cec_notifier_get_conn(d, m->conn);
return 0;
}
}
/* Hardware support must be added in the cec_dmi_match_table */
dev_warn(dev, "CEC notifier not configured for this hardware\n");
return -ENODEV;
}
#else
static int cros_ec_cec_get_notifier(struct device *dev,
struct cec_notifier **notify)
{
return -ENODEV;
}
#endif
static int cros_ec_cec_probe(struct platform_device *pdev)
{
struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent);
struct cros_ec_device *cros_ec = ec_dev->ec_dev;
struct cros_ec_cec *cros_ec_cec;
int ret;
cros_ec_cec = devm_kzalloc(&pdev->dev, sizeof(*cros_ec_cec),
GFP_KERNEL);
if (!cros_ec_cec)
return -ENOMEM;
platform_set_drvdata(pdev, cros_ec_cec);
cros_ec_cec->cros_ec = cros_ec;
ret = cros_ec_cec_get_notifier(&pdev->dev, &cros_ec_cec->notify);
if (ret)
return ret;
ret = device_init_wakeup(&pdev->dev, 1);
if (ret) {
dev_err(&pdev->dev, "failed to initialize wakeup\n");
return ret;
}
cros_ec_cec->adap = cec_allocate_adapter(&cros_ec_cec_ops, cros_ec_cec,
DRV_NAME, CEC_CAP_DEFAULTS, 1);
if (IS_ERR(cros_ec_cec->adap))
return PTR_ERR(cros_ec_cec->adap);
/* Get CEC events from the EC. */
cros_ec_cec->notifier.notifier_call = cros_ec_cec_event;
ret = blocking_notifier_chain_register(&cros_ec->event_notifier,
&cros_ec_cec->notifier);
if (ret) {
dev_err(&pdev->dev, "failed to register notifier\n");
cec_delete_adapter(cros_ec_cec->adap);
return ret;
}
ret = cec_register_adapter(cros_ec_cec->adap, &pdev->dev);
if (ret < 0) {
cec_delete_adapter(cros_ec_cec->adap);
return ret;
}
cec_register_cec_notifier(cros_ec_cec->adap, cros_ec_cec->notify);
return 0;
}
static int cros_ec_cec_remove(struct platform_device *pdev)
{
struct cros_ec_cec *cros_ec_cec = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
int ret;
ret = blocking_notifier_chain_unregister(
&cros_ec_cec->cros_ec->event_notifier,
&cros_ec_cec->notifier);
if (ret) {
dev_err(dev, "failed to unregister notifier\n");
return ret;
}
cec_unregister_adapter(cros_ec_cec->adap);
if (cros_ec_cec->notify)
cec_notifier_put(cros_ec_cec->notify);
return 0;
}
static struct platform_driver cros_ec_cec_driver = {
.probe = cros_ec_cec_probe,
.remove = cros_ec_cec_remove,
.driver = {
.name = DRV_NAME,
.pm = &cros_ec_cec_pm_ops,
},
};
module_platform_driver(cros_ec_cec_driver);
MODULE_DESCRIPTION("CEC driver for ChromeOS ECs");
MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
...@@ -202,26 +202,6 @@ config MFD_CROS_EC ...@@ -202,26 +202,6 @@ config MFD_CROS_EC
You also need to enable the driver for the bus you are using. The You also need to enable the driver for the bus you are using. The
protocol for talking to the EC is defined by the bus driver. protocol for talking to the EC is defined by the bus driver.
config MFD_CROS_EC_I2C
tristate "ChromeOS Embedded Controller (I2C)"
depends on MFD_CROS_EC && I2C
help
If you say Y here, you get support for talking to the ChromeOS
EC through an I2C bus. This uses a simple byte-level protocol with
a checksum. Failing accesses will be retried three times to
improve reliability.
config MFD_CROS_EC_SPI
tristate "ChromeOS Embedded Controller (SPI)"
depends on MFD_CROS_EC && SPI
---help---
If you say Y here, you get support for talking to the ChromeOS EC
through a SPI bus, using a byte-level protocol. Since the EC's
response time cannot be guaranteed, we support ignoring
'pre-amble' bytes before the response actually starts.
config MFD_CROS_EC_CHARDEV config MFD_CROS_EC_CHARDEV
tristate "Chrome OS Embedded Controller userspace device interface" tristate "Chrome OS Embedded Controller userspace device interface"
depends on MFD_CROS_EC depends on MFD_CROS_EC
...@@ -232,6 +212,56 @@ config MFD_CROS_EC_CHARDEV ...@@ -232,6 +212,56 @@ config MFD_CROS_EC_CHARDEV
If you have a supported Chromebook, choose Y or M here. If you have a supported Chromebook, choose Y or M here.
The module will be called cros_ec_dev. The module will be called cros_ec_dev.
config MFD_MADERA
tristate "Cirrus Logic Madera codecs"
select MFD_CORE
select REGMAP
select REGMAP_IRQ
select MADERA_IRQ
select PINCTRL
select PINCTRL_MADERA
help
Support for the Cirrus Logic Madera platform audio codecs
config MFD_MADERA_I2C
tristate "Cirrus Logic Madera codecs with I2C"
depends on MFD_MADERA
depends on I2C
select REGMAP_I2C
help
Support for the Cirrus Logic Madera platform audio SoC
core functionality controlled via I2C.
config MFD_MADERA_SPI
tristate "Cirrus Logic Madera codecs with SPI"
depends on MFD_MADERA
depends on SPI_MASTER
select REGMAP_SPI
help
Support for the Cirrus Logic Madera platform audio SoC
core functionality controlled via SPI.
config MFD_CS47L35
bool "Cirrus Logic CS47L35"
select PINCTRL_CS47L35
depends on MFD_MADERA
help
Support for Cirrus Logic CS47L35 Smart Codec
config MFD_CS47L85
bool "Cirrus Logic CS47L85"
select PINCTRL_CS47L85
depends on MFD_MADERA
help
Support for Cirrus Logic CS47L85 Smart Codec
config MFD_CS47L90
bool "Cirrus Logic CS47L90/91"
select PINCTRL_CS47L90
depends on MFD_MADERA
help
Support for Cirrus Logic CS47L90 and CS47L91 Smart Codecs
config MFD_ASIC3 config MFD_ASIC3
bool "Compaq ASIC3" bool "Compaq ASIC3"
depends on GPIOLIB && ARM depends on GPIOLIB && ARM
...@@ -1787,6 +1817,19 @@ config MFD_STW481X ...@@ -1787,6 +1817,19 @@ config MFD_STW481X
in various ST Microelectronics and ST-Ericsson embedded in various ST Microelectronics and ST-Ericsson embedded
Nomadik series. Nomadik series.
config MFD_ROHM_BD718XX
tristate "ROHM BD71837 Power Management IC"
depends on I2C=y
depends on OF
select REGMAP_I2C
select REGMAP_IRQ
select MFD_CORE
help
Select this option to get support for the ROHM BD71837
Power Management ICs. BD71837 is designed to power processors like
NXP i.MX8. It contains 8 BUCK outputs and 7 LDOs, voltage monitoring
and emergency shut down as well as 32,768KHz clock output.
config MFD_STM32_LPTIMER config MFD_STM32_LPTIMER
tristate "Support for STM32 Low-Power Timer" tristate "Support for STM32 Low-Power Timer"
depends on (ARCH_STM32 && OF) || COMPILE_TEST depends on (ARCH_STM32 && OF) || COMPILE_TEST
......
...@@ -14,8 +14,6 @@ obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o ...@@ -14,8 +14,6 @@ obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
cros_ec_core-objs := cros_ec.o cros_ec_core-objs := cros_ec.o
obj-$(CONFIG_MFD_CROS_EC) += cros_ec_core.o obj-$(CONFIG_MFD_CROS_EC) += cros_ec_core.o
obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o
obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o
obj-$(CONFIG_MFD_CROS_EC_CHARDEV) += cros_ec_dev.o obj-$(CONFIG_MFD_CROS_EC_CHARDEV) += cros_ec_dev.o
obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o
...@@ -72,6 +70,20 @@ wm8994-objs := wm8994-core.o wm8994-irq.o wm8994-regmap.o ...@@ -72,6 +70,20 @@ wm8994-objs := wm8994-core.o wm8994-irq.o wm8994-regmap.o
obj-$(CONFIG_MFD_WM8994) += wm8994.o obj-$(CONFIG_MFD_WM8994) += wm8994.o
obj-$(CONFIG_MFD_WM97xx) += wm97xx-core.o obj-$(CONFIG_MFD_WM97xx) += wm97xx-core.o
madera-objs := madera-core.o
ifeq ($(CONFIG_MFD_CS47L35),y)
madera-objs += cs47l35-tables.o
endif
ifeq ($(CONFIG_MFD_CS47L85),y)
madera-objs += cs47l85-tables.o
endif
ifeq ($(CONFIG_MFD_CS47L90),y)
madera-objs += cs47l90-tables.o
endif
obj-$(CONFIG_MFD_MADERA) += madera.o
obj-$(CONFIG_MFD_MADERA_I2C) += madera-i2c.o
obj-$(CONFIG_MFD_MADERA_SPI) += madera-spi.o
obj-$(CONFIG_TPS6105X) += tps6105x.o obj-$(CONFIG_TPS6105X) += tps6105x.o
obj-$(CONFIG_TPS65010) += tps65010.o obj-$(CONFIG_TPS65010) += tps65010.o
obj-$(CONFIG_TPS6507X) += tps6507x.o obj-$(CONFIG_TPS6507X) += tps6507x.o
...@@ -227,4 +239,5 @@ obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o ...@@ -227,4 +239,5 @@ obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o
obj-$(CONFIG_MFD_MXS_LRADC) += mxs-lradc.o obj-$(CONFIG_MFD_MXS_LRADC) += mxs-lradc.o
obj-$(CONFIG_MFD_SC27XX_PMIC) += sprd-sc27xx-spi.o obj-$(CONFIG_MFD_SC27XX_PMIC) += sprd-sc27xx-spi.o
obj-$(CONFIG_RAVE_SP_CORE) += rave-sp.o obj-$(CONFIG_RAVE_SP_CORE) += rave-sp.o
obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/ktime.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mfd/arizona/core.h> #include <linux/mfd/arizona/core.h>
...@@ -236,22 +237,39 @@ static irqreturn_t arizona_overclocked(int irq, void *data) ...@@ -236,22 +237,39 @@ static irqreturn_t arizona_overclocked(int irq, void *data)
#define ARIZONA_REG_POLL_DELAY_US 7500 #define ARIZONA_REG_POLL_DELAY_US 7500
static inline bool arizona_poll_reg_delay(ktime_t timeout)
{
if (ktime_compare(ktime_get(), timeout) > 0)
return false;
usleep_range(ARIZONA_REG_POLL_DELAY_US / 2, ARIZONA_REG_POLL_DELAY_US);
return true;
}
static int arizona_poll_reg(struct arizona *arizona, static int arizona_poll_reg(struct arizona *arizona,
int timeout_ms, unsigned int reg, int timeout_ms, unsigned int reg,
unsigned int mask, unsigned int target) unsigned int mask, unsigned int target)
{ {
ktime_t timeout = ktime_add_us(ktime_get(), timeout_ms * USEC_PER_MSEC);
unsigned int val = 0; unsigned int val = 0;
int ret; int ret;
ret = regmap_read_poll_timeout(arizona->regmap, do {
reg, val, ((val & mask) == target), ret = regmap_read(arizona->regmap, reg, &val);
ARIZONA_REG_POLL_DELAY_US,
timeout_ms * 1000);
if (ret)
dev_err(arizona->dev, "Polling reg 0x%x timed out: %x\n",
reg, val);
return ret; if ((val & mask) == target)
return 0;
} while (arizona_poll_reg_delay(timeout));
if (ret) {
dev_err(arizona->dev, "Failed polling reg 0x%x: %d\n",
reg, ret);
return ret;
}
dev_err(arizona->dev, "Polling reg 0x%x timed out: %x\n", reg, val);
return -ETIMEDOUT;
} }
static int arizona_wait_for_boot(struct arizona *arizona) static int arizona_wait_for_boot(struct arizona *arizona)
......
...@@ -349,6 +349,8 @@ static int as3722_i2c_of_probe(struct i2c_client *i2c, ...@@ -349,6 +349,8 @@ static int as3722_i2c_of_probe(struct i2c_client *i2c,
"ams,enable-internal-int-pullup"); "ams,enable-internal-int-pullup");
as3722->en_intern_i2c_pullup = of_property_read_bool(np, as3722->en_intern_i2c_pullup = of_property_read_bool(np,
"ams,enable-internal-i2c-pullup"); "ams,enable-internal-i2c-pullup");
as3722->en_ac_ok_pwr_on = of_property_read_bool(np,
"ams,enable-ac-ok-power-on");
as3722->irq_flags = irqd_get_trigger_type(irq_data); as3722->irq_flags = irqd_get_trigger_type(irq_data);
dev_dbg(&i2c->dev, "IRQ flags are 0x%08lx\n", as3722->irq_flags); dev_dbg(&i2c->dev, "IRQ flags are 0x%08lx\n", as3722->irq_flags);
return 0; return 0;
...@@ -360,6 +362,7 @@ static int as3722_i2c_probe(struct i2c_client *i2c, ...@@ -360,6 +362,7 @@ static int as3722_i2c_probe(struct i2c_client *i2c,
struct as3722 *as3722; struct as3722 *as3722;
unsigned long irq_flags; unsigned long irq_flags;
int ret; int ret;
u8 val = 0;
as3722 = devm_kzalloc(&i2c->dev, sizeof(struct as3722), GFP_KERNEL); as3722 = devm_kzalloc(&i2c->dev, sizeof(struct as3722), GFP_KERNEL);
if (!as3722) if (!as3722)
...@@ -398,6 +401,15 @@ static int as3722_i2c_probe(struct i2c_client *i2c, ...@@ -398,6 +401,15 @@ static int as3722_i2c_probe(struct i2c_client *i2c,
if (ret < 0) if (ret < 0)
return ret; return ret;
if (as3722->en_ac_ok_pwr_on)
val = AS3722_CTRL_SEQU1_AC_OK_PWR_ON;
ret = as3722_update_bits(as3722, AS3722_CTRL_SEQU1_REG,
AS3722_CTRL_SEQU1_AC_OK_PWR_ON, val);
if (ret < 0) {
dev_err(as3722->dev, "CTRLsequ1 update failed: %d\n", ret);
return ret;
}
ret = devm_mfd_add_devices(&i2c->dev, -1, as3722_devs, ret = devm_mfd_add_devices(&i2c->dev, -1, as3722_devs,
ARRAY_SIZE(as3722_devs), NULL, 0, ARRAY_SIZE(as3722_devs), NULL, 0,
regmap_irq_get_domain(as3722->irq_data)); regmap_irq_get_domain(as3722->irq_data));
......
...@@ -65,6 +65,7 @@ static const struct of_device_id axp20x_i2c_of_match[] = { ...@@ -65,6 +65,7 @@ static const struct of_device_id axp20x_i2c_of_match[] = {
{ .compatible = "x-powers,axp202", .data = (void *)AXP202_ID }, { .compatible = "x-powers,axp202", .data = (void *)AXP202_ID },
{ .compatible = "x-powers,axp209", .data = (void *)AXP209_ID }, { .compatible = "x-powers,axp209", .data = (void *)AXP209_ID },
{ .compatible = "x-powers,axp221", .data = (void *)AXP221_ID }, { .compatible = "x-powers,axp221", .data = (void *)AXP221_ID },
{ .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match); MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match);
...@@ -74,6 +75,7 @@ static const struct i2c_device_id axp20x_i2c_id[] = { ...@@ -74,6 +75,7 @@ static const struct i2c_device_id axp20x_i2c_id[] = {
{ "axp202", 0 }, { "axp202", 0 },
{ "axp209", 0 }, { "axp209", 0 },
{ "axp221", 0 }, { "axp221", 0 },
{ "axp806", 0 },
{ }, { },
}; };
MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id); MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
......
...@@ -221,6 +221,11 @@ static const struct resource axp803_pek_resources[] = { ...@@ -221,6 +221,11 @@ static const struct resource axp803_pek_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"), DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
}; };
static const struct resource axp806_pek_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP806_IRQ_POK_RISE, "PEK_DBR"),
DEFINE_RES_IRQ_NAMED(AXP806_IRQ_POK_FALL, "PEK_DBF"),
};
static const struct resource axp809_pek_resources[] = { static const struct resource axp809_pek_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_RIS_EDGE, "PEK_DBR"), DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"), DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
...@@ -730,6 +735,15 @@ static const struct mfd_cell axp803_cells[] = { ...@@ -730,6 +735,15 @@ static const struct mfd_cell axp803_cells[] = {
{ .name = "axp20x-regulator" }, { .name = "axp20x-regulator" },
}; };
static const struct mfd_cell axp806_self_working_cells[] = {
{
.name = "axp221-pek",
.num_resources = ARRAY_SIZE(axp806_pek_resources),
.resources = axp806_pek_resources,
},
{ .name = "axp20x-regulator" },
};
static const struct mfd_cell axp806_cells[] = { static const struct mfd_cell axp806_cells[] = {
{ {
.id = 2, .id = 2,
...@@ -842,8 +856,14 @@ int axp20x_match_device(struct axp20x_dev *axp20x) ...@@ -842,8 +856,14 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
axp20x->regmap_irq_chip = &axp803_regmap_irq_chip; axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
break; break;
case AXP806_ID: case AXP806_ID:
axp20x->nr_cells = ARRAY_SIZE(axp806_cells); if (of_property_read_bool(axp20x->dev->of_node,
axp20x->cells = axp806_cells; "x-powers,self-working-mode")) {
axp20x->nr_cells = ARRAY_SIZE(axp806_self_working_cells);
axp20x->cells = axp806_self_working_cells;
} else {
axp20x->nr_cells = ARRAY_SIZE(axp806_cells);
axp20x->cells = axp806_cells;
}
axp20x->regmap_cfg = &axp806_regmap_config; axp20x->regmap_cfg = &axp806_regmap_config;
axp20x->regmap_irq_chip = &axp806_regmap_irq_chip; axp20x->regmap_irq_chip = &axp806_regmap_irq_chip;
break; break;
...@@ -901,7 +921,9 @@ int axp20x_device_probe(struct axp20x_dev *axp20x) ...@@ -901,7 +921,9 @@ int axp20x_device_probe(struct axp20x_dev *axp20x)
*/ */
if (axp20x->variant == AXP806_ID) { if (axp20x->variant == AXP806_ID) {
if (of_property_read_bool(axp20x->dev->of_node, if (of_property_read_bool(axp20x->dev->of_node,
"x-powers,master-mode")) "x-powers,master-mode") ||
of_property_read_bool(axp20x->dev->of_node,
"x-powers,self-working-mode"))
regmap_write(axp20x->regmap, AXP806_REG_ADDR_EXT, regmap_write(axp20x->regmap, AXP806_REG_ADDR_EXT,
AXP806_REG_ADDR_EXT_ADDR_MASTER_MODE); AXP806_REG_ADDR_EXT_ADDR_MASTER_MODE);
else else
......
...@@ -378,10 +378,18 @@ static void cros_ec_sensors_register(struct cros_ec_dev *ec) ...@@ -378,10 +378,18 @@ static void cros_ec_sensors_register(struct cros_ec_dev *ec)
kfree(msg); kfree(msg);
} }
static const struct mfd_cell cros_ec_cec_cells[] = {
{ .name = "cros-ec-cec" }
};
static const struct mfd_cell cros_ec_rtc_cells[] = { static const struct mfd_cell cros_ec_rtc_cells[] = {
{ .name = "cros-ec-rtc" } { .name = "cros-ec-rtc" }
}; };
static const struct mfd_cell cros_usbpd_charger_cells[] = {
{ .name = "cros-usbpd-charger" }
};
static int ec_device_probe(struct platform_device *pdev) static int ec_device_probe(struct platform_device *pdev)
{ {
int retval = -ENOMEM; int retval = -ENOMEM;
...@@ -420,6 +428,18 @@ static int ec_device_probe(struct platform_device *pdev) ...@@ -420,6 +428,18 @@ static int ec_device_probe(struct platform_device *pdev)
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE)) if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
cros_ec_sensors_register(ec); cros_ec_sensors_register(ec);
/* Check whether this EC instance has CEC host command support */
if (cros_ec_check_features(ec, EC_FEATURE_CEC)) {
retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
cros_ec_cec_cells,
ARRAY_SIZE(cros_ec_cec_cells),
NULL, 0, NULL);
if (retval)
dev_err(ec->dev,
"failed to add cros-ec-cec device: %d\n",
retval);
}
/* Check whether this EC instance has RTC host command support */ /* Check whether this EC instance has RTC host command support */
if (cros_ec_check_features(ec, EC_FEATURE_RTC)) { if (cros_ec_check_features(ec, EC_FEATURE_RTC)) {
retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO, retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
...@@ -432,6 +452,18 @@ static int ec_device_probe(struct platform_device *pdev) ...@@ -432,6 +452,18 @@ static int ec_device_probe(struct platform_device *pdev)
retval); retval);
} }
/* Check whether this EC instance has the PD charge manager */
if (cros_ec_check_features(ec, EC_FEATURE_USB_PD)) {
retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
cros_usbpd_charger_cells,
ARRAY_SIZE(cros_usbpd_charger_cells),
NULL, 0, NULL);
if (retval)
dev_err(ec->dev,
"failed to add cros-usbpd-charger device: %d\n",
retval);
}
/* Take control of the lightbar from the EC. */ /* Take control of the lightbar from the EC. */
lb_manual_suspend_ctrl(ec, 1); lb_manual_suspend_ctrl(ec, 1);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -76,7 +76,7 @@ static struct resource da9063_hwmon_resources[] = { ...@@ -76,7 +76,7 @@ static struct resource da9063_hwmon_resources[] = {
}; };
static const struct mfd_cell da9063_devs[] = { static const struct mfd_cell da9063_common_devs[] = {
{ {
.name = DA9063_DRVNAME_REGULATORS, .name = DA9063_DRVNAME_REGULATORS,
.num_resources = ARRAY_SIZE(da9063_regulators_resources), .num_resources = ARRAY_SIZE(da9063_regulators_resources),
...@@ -100,15 +100,19 @@ static const struct mfd_cell da9063_devs[] = { ...@@ -100,15 +100,19 @@ static const struct mfd_cell da9063_devs[] = {
.resources = da9063_onkey_resources, .resources = da9063_onkey_resources,
.of_compatible = "dlg,da9063-onkey", .of_compatible = "dlg,da9063-onkey",
}, },
{
.name = DA9063_DRVNAME_VIBRATION,
},
};
/* Only present on DA9063 , not on DA9063L */
static const struct mfd_cell da9063_devs[] = {
{ {
.name = DA9063_DRVNAME_RTC, .name = DA9063_DRVNAME_RTC,
.num_resources = ARRAY_SIZE(da9063_rtc_resources), .num_resources = ARRAY_SIZE(da9063_rtc_resources),
.resources = da9063_rtc_resources, .resources = da9063_rtc_resources,
.of_compatible = "dlg,da9063-rtc", .of_compatible = "dlg,da9063-rtc",
}, },
{
.name = DA9063_DRVNAME_VIBRATION,
},
}; };
static int da9063_clear_fault_log(struct da9063 *da9063) static int da9063_clear_fault_log(struct da9063 *da9063)
...@@ -192,7 +196,7 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq) ...@@ -192,7 +196,7 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
dev_err(da9063->dev, "Cannot read chip model id.\n"); dev_err(da9063->dev, "Cannot read chip model id.\n");
return -EIO; return -EIO;
} }
if (model != PMIC_DA9063) { if (model != PMIC_CHIP_ID_DA9063) {
dev_err(da9063->dev, "Invalid chip model id: 0x%02x\n", model); dev_err(da9063->dev, "Invalid chip model id: 0x%02x\n", model);
return -ENODEV; return -ENODEV;
} }
...@@ -215,7 +219,6 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq) ...@@ -215,7 +219,6 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
return -ENODEV; return -ENODEV;
} }
da9063->model = model;
da9063->variant_code = variant_code; da9063->variant_code = variant_code;
ret = da9063_irq_init(da9063); ret = da9063_irq_init(da9063);
...@@ -226,19 +229,26 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq) ...@@ -226,19 +229,26 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
da9063->irq_base = regmap_irq_chip_get_base(da9063->regmap_irq); da9063->irq_base = regmap_irq_chip_get_base(da9063->regmap_irq);
ret = mfd_add_devices(da9063->dev, -1, da9063_devs, ret = devm_mfd_add_devices(da9063->dev, PLATFORM_DEVID_NONE,
ARRAY_SIZE(da9063_devs), NULL, da9063->irq_base, da9063_common_devs,
NULL); ARRAY_SIZE(da9063_common_devs),
if (ret) NULL, da9063->irq_base, NULL);
dev_err(da9063->dev, "Cannot add MFD cells\n"); if (ret) {
dev_err(da9063->dev, "Failed to add child devices\n");
return ret;
}
return ret; if (da9063->type == PMIC_TYPE_DA9063) {
} ret = devm_mfd_add_devices(da9063->dev, PLATFORM_DEVID_NONE,
da9063_devs, ARRAY_SIZE(da9063_devs),
NULL, da9063->irq_base, NULL);
if (ret) {
dev_err(da9063->dev, "Failed to add child devices\n");
return ret;
}
}
void da9063_device_exit(struct da9063 *da9063) return ret;
{
mfd_remove_devices(da9063->dev);
da9063_irq_exit(da9063);
} }
MODULE_DESCRIPTION("PMIC driver for Dialog DA9063"); MODULE_DESCRIPTION("PMIC driver for Dialog DA9063");
......
This diff is collapsed.
...@@ -28,132 +28,145 @@ ...@@ -28,132 +28,145 @@
static const struct regmap_irq da9063_irqs[] = { static const struct regmap_irq da9063_irqs[] = {
/* DA9063 event A register */ /* DA9063 event A register */
[DA9063_IRQ_ONKEY] = { REGMAP_IRQ_REG(DA9063_IRQ_ONKEY,
.reg_offset = DA9063_REG_EVENT_A_OFFSET, DA9063_REG_EVENT_A_OFFSET, DA9063_M_ONKEY),
.mask = DA9063_M_ONKEY, REGMAP_IRQ_REG(DA9063_IRQ_ALARM,
}, DA9063_REG_EVENT_A_OFFSET, DA9063_M_ALARM),
[DA9063_IRQ_ALARM] = { REGMAP_IRQ_REG(DA9063_IRQ_TICK,
.reg_offset = DA9063_REG_EVENT_A_OFFSET, DA9063_REG_EVENT_A_OFFSET, DA9063_M_TICK),
.mask = DA9063_M_ALARM, REGMAP_IRQ_REG(DA9063_IRQ_ADC_RDY,
}, DA9063_REG_EVENT_A_OFFSET, DA9063_M_ADC_RDY),
[DA9063_IRQ_TICK] = { REGMAP_IRQ_REG(DA9063_IRQ_SEQ_RDY,
.reg_offset = DA9063_REG_EVENT_A_OFFSET, DA9063_REG_EVENT_A_OFFSET, DA9063_M_SEQ_RDY),
.mask = DA9063_M_TICK,
},
[DA9063_IRQ_ADC_RDY] = {
.reg_offset = DA9063_REG_EVENT_A_OFFSET,
.mask = DA9063_M_ADC_RDY,
},
[DA9063_IRQ_SEQ_RDY] = {
.reg_offset = DA9063_REG_EVENT_A_OFFSET,
.mask = DA9063_M_SEQ_RDY,
},
/* DA9063 event B register */ /* DA9063 event B register */
[DA9063_IRQ_WAKE] = { REGMAP_IRQ_REG(DA9063_IRQ_WAKE,
.reg_offset = DA9063_REG_EVENT_B_OFFSET, DA9063_REG_EVENT_B_OFFSET, DA9063_M_WAKE),
.mask = DA9063_M_WAKE, REGMAP_IRQ_REG(DA9063_IRQ_TEMP,
}, DA9063_REG_EVENT_B_OFFSET, DA9063_M_TEMP),
[DA9063_IRQ_TEMP] = { REGMAP_IRQ_REG(DA9063_IRQ_COMP_1V2,
.reg_offset = DA9063_REG_EVENT_B_OFFSET, DA9063_REG_EVENT_B_OFFSET, DA9063_M_COMP_1V2),
.mask = DA9063_M_TEMP, REGMAP_IRQ_REG(DA9063_IRQ_LDO_LIM,
}, DA9063_REG_EVENT_B_OFFSET, DA9063_M_LDO_LIM),
[DA9063_IRQ_COMP_1V2] = { REGMAP_IRQ_REG(DA9063_IRQ_REG_UVOV,
.reg_offset = DA9063_REG_EVENT_B_OFFSET, DA9063_REG_EVENT_B_OFFSET, DA9063_M_UVOV),
.mask = DA9063_M_COMP_1V2, REGMAP_IRQ_REG(DA9063_IRQ_DVC_RDY,
}, DA9063_REG_EVENT_B_OFFSET, DA9063_M_DVC_RDY),
[DA9063_IRQ_LDO_LIM] = { REGMAP_IRQ_REG(DA9063_IRQ_VDD_MON,
.reg_offset = DA9063_REG_EVENT_B_OFFSET, DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_MON),
.mask = DA9063_M_LDO_LIM, REGMAP_IRQ_REG(DA9063_IRQ_WARN,
}, DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_WARN),
[DA9063_IRQ_REG_UVOV] = {
.reg_offset = DA9063_REG_EVENT_B_OFFSET,
.mask = DA9063_M_UVOV,
},
[DA9063_IRQ_DVC_RDY] = {
.reg_offset = DA9063_REG_EVENT_B_OFFSET,
.mask = DA9063_M_DVC_RDY,
},
[DA9063_IRQ_VDD_MON] = {
.reg_offset = DA9063_REG_EVENT_B_OFFSET,
.mask = DA9063_M_VDD_MON,
},
[DA9063_IRQ_WARN] = {
.reg_offset = DA9063_REG_EVENT_B_OFFSET,
.mask = DA9063_M_VDD_WARN,
},
/* DA9063 event C register */ /* DA9063 event C register */
[DA9063_IRQ_GPI0] = { REGMAP_IRQ_REG(DA9063_IRQ_GPI0,
.reg_offset = DA9063_REG_EVENT_C_OFFSET, DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI0),
.mask = DA9063_M_GPI0, REGMAP_IRQ_REG(DA9063_IRQ_GPI1,
}, DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI1),
[DA9063_IRQ_GPI1] = { REGMAP_IRQ_REG(DA9063_IRQ_GPI2,
.reg_offset = DA9063_REG_EVENT_C_OFFSET, DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI2),
.mask = DA9063_M_GPI1, REGMAP_IRQ_REG(DA9063_IRQ_GPI3,
}, DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI3),
[DA9063_IRQ_GPI2] = { REGMAP_IRQ_REG(DA9063_IRQ_GPI4,
.reg_offset = DA9063_REG_EVENT_C_OFFSET, DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI4),
.mask = DA9063_M_GPI2, REGMAP_IRQ_REG(DA9063_IRQ_GPI5,
}, DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI5),
[DA9063_IRQ_GPI3] = { REGMAP_IRQ_REG(DA9063_IRQ_GPI6,
.reg_offset = DA9063_REG_EVENT_C_OFFSET, DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI6),
.mask = DA9063_M_GPI3, REGMAP_IRQ_REG(DA9063_IRQ_GPI7,
}, DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI7),
[DA9063_IRQ_GPI4] = {
.reg_offset = DA9063_REG_EVENT_C_OFFSET,
.mask = DA9063_M_GPI4,
},
[DA9063_IRQ_GPI5] = {
.reg_offset = DA9063_REG_EVENT_C_OFFSET,
.mask = DA9063_M_GPI5,
},
[DA9063_IRQ_GPI6] = {
.reg_offset = DA9063_REG_EVENT_C_OFFSET,
.mask = DA9063_M_GPI6,
},
[DA9063_IRQ_GPI7] = {
.reg_offset = DA9063_REG_EVENT_C_OFFSET,
.mask = DA9063_M_GPI7,
},
/* DA9063 event D register */ /* DA9063 event D register */
[DA9063_IRQ_GPI8] = { REGMAP_IRQ_REG(DA9063_IRQ_GPI8,
.reg_offset = DA9063_REG_EVENT_D_OFFSET, DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI8),
.mask = DA9063_M_GPI8, REGMAP_IRQ_REG(DA9063_IRQ_GPI9,
}, DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI9),
[DA9063_IRQ_GPI9] = { REGMAP_IRQ_REG(DA9063_IRQ_GPI10,
.reg_offset = DA9063_REG_EVENT_D_OFFSET, DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI10),
.mask = DA9063_M_GPI9, REGMAP_IRQ_REG(DA9063_IRQ_GPI11,
}, DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI11),
[DA9063_IRQ_GPI10] = { REGMAP_IRQ_REG(DA9063_IRQ_GPI12,
.reg_offset = DA9063_REG_EVENT_D_OFFSET, DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI12),
.mask = DA9063_M_GPI10, REGMAP_IRQ_REG(DA9063_IRQ_GPI13,
}, DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI13),
[DA9063_IRQ_GPI11] = { REGMAP_IRQ_REG(DA9063_IRQ_GPI14,
.reg_offset = DA9063_REG_EVENT_D_OFFSET, DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI14),
.mask = DA9063_M_GPI11, REGMAP_IRQ_REG(DA9063_IRQ_GPI15,
}, DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI15),
[DA9063_IRQ_GPI12] = {
.reg_offset = DA9063_REG_EVENT_D_OFFSET,
.mask = DA9063_M_GPI12,
},
[DA9063_IRQ_GPI13] = {
.reg_offset = DA9063_REG_EVENT_D_OFFSET,
.mask = DA9063_M_GPI13,
},
[DA9063_IRQ_GPI14] = {
.reg_offset = DA9063_REG_EVENT_D_OFFSET,
.mask = DA9063_M_GPI14,
},
[DA9063_IRQ_GPI15] = {
.reg_offset = DA9063_REG_EVENT_D_OFFSET,
.mask = DA9063_M_GPI15,
},
}; };
static const struct regmap_irq_chip da9063_irq_chip = { static const struct regmap_irq_chip da9063_irq_chip = {
.name = "da9063-irq", .name = "da9063-irq",
.irqs = da9063_irqs, .irqs = da9063_irqs,
.num_irqs = DA9063_NUM_IRQ, .num_irqs = ARRAY_SIZE(da9063_irqs),
.num_regs = 4,
.status_base = DA9063_REG_EVENT_A,
.mask_base = DA9063_REG_IRQ_MASK_A,
.ack_base = DA9063_REG_EVENT_A,
.init_ack_masked = true,
};
static const struct regmap_irq da9063l_irqs[] = {
/* DA9063 event A register */
REGMAP_IRQ_REG(DA9063_IRQ_ONKEY,
DA9063_REG_EVENT_A_OFFSET, DA9063_M_ONKEY),
REGMAP_IRQ_REG(DA9063_IRQ_ADC_RDY,
DA9063_REG_EVENT_A_OFFSET, DA9063_M_ADC_RDY),
REGMAP_IRQ_REG(DA9063_IRQ_SEQ_RDY,
DA9063_REG_EVENT_A_OFFSET, DA9063_M_SEQ_RDY),
/* DA9063 event B register */
REGMAP_IRQ_REG(DA9063_IRQ_WAKE,
DA9063_REG_EVENT_B_OFFSET, DA9063_M_WAKE),
REGMAP_IRQ_REG(DA9063_IRQ_TEMP,
DA9063_REG_EVENT_B_OFFSET, DA9063_M_TEMP),
REGMAP_IRQ_REG(DA9063_IRQ_COMP_1V2,
DA9063_REG_EVENT_B_OFFSET, DA9063_M_COMP_1V2),
REGMAP_IRQ_REG(DA9063_IRQ_LDO_LIM,
DA9063_REG_EVENT_B_OFFSET, DA9063_M_LDO_LIM),
REGMAP_IRQ_REG(DA9063_IRQ_REG_UVOV,
DA9063_REG_EVENT_B_OFFSET, DA9063_M_UVOV),
REGMAP_IRQ_REG(DA9063_IRQ_DVC_RDY,
DA9063_REG_EVENT_B_OFFSET, DA9063_M_DVC_RDY),
REGMAP_IRQ_REG(DA9063_IRQ_VDD_MON,
DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_MON),
REGMAP_IRQ_REG(DA9063_IRQ_WARN,
DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_WARN),
/* DA9063 event C register */
REGMAP_IRQ_REG(DA9063_IRQ_GPI0,
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI0),
REGMAP_IRQ_REG(DA9063_IRQ_GPI1,
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI1),
REGMAP_IRQ_REG(DA9063_IRQ_GPI2,
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI2),
REGMAP_IRQ_REG(DA9063_IRQ_GPI3,
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI3),
REGMAP_IRQ_REG(DA9063_IRQ_GPI4,
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI4),
REGMAP_IRQ_REG(DA9063_IRQ_GPI5,
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI5),
REGMAP_IRQ_REG(DA9063_IRQ_GPI6,
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI6),
REGMAP_IRQ_REG(DA9063_IRQ_GPI7,
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI7),
/* DA9063 event D register */
REGMAP_IRQ_REG(DA9063_IRQ_GPI8,
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI8),
REGMAP_IRQ_REG(DA9063_IRQ_GPI9,
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI9),
REGMAP_IRQ_REG(DA9063_IRQ_GPI10,
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI10),
REGMAP_IRQ_REG(DA9063_IRQ_GPI11,
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI11),
REGMAP_IRQ_REG(DA9063_IRQ_GPI12,
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI12),
REGMAP_IRQ_REG(DA9063_IRQ_GPI13,
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI13),
REGMAP_IRQ_REG(DA9063_IRQ_GPI14,
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI14),
REGMAP_IRQ_REG(DA9063_IRQ_GPI15,
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI15),
};
static const struct regmap_irq_chip da9063l_irq_chip = {
.name = "da9063l-irq",
.irqs = da9063l_irqs,
.num_irqs = ARRAY_SIZE(da9063l_irqs),
.num_regs = 4, .num_regs = 4,
.status_base = DA9063_REG_EVENT_A, .status_base = DA9063_REG_EVENT_A,
.mask_base = DA9063_REG_IRQ_MASK_A, .mask_base = DA9063_REG_IRQ_MASK_A,
...@@ -163,6 +176,7 @@ static const struct regmap_irq_chip da9063_irq_chip = { ...@@ -163,6 +176,7 @@ static const struct regmap_irq_chip da9063_irq_chip = {
int da9063_irq_init(struct da9063 *da9063) int da9063_irq_init(struct da9063 *da9063)
{ {
const struct regmap_irq_chip *irq_chip;
int ret; int ret;
if (!da9063->chip_irq) { if (!da9063->chip_irq) {
...@@ -170,10 +184,15 @@ int da9063_irq_init(struct da9063 *da9063) ...@@ -170,10 +184,15 @@ int da9063_irq_init(struct da9063 *da9063)
return -EINVAL; return -EINVAL;
} }
ret = regmap_add_irq_chip(da9063->regmap, da9063->chip_irq, if (da9063->type == PMIC_TYPE_DA9063)
irq_chip = &da9063_irq_chip;
else
irq_chip = &da9063l_irq_chip;
ret = devm_regmap_add_irq_chip(da9063->dev, da9063->regmap,
da9063->chip_irq,
IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED, IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
da9063->irq_base, &da9063_irq_chip, da9063->irq_base, irq_chip, &da9063->regmap_irq);
&da9063->regmap_irq);
if (ret) { if (ret) {
dev_err(da9063->dev, "Failed to reguest IRQ %d: %d\n", dev_err(da9063->dev, "Failed to reguest IRQ %d: %d\n",
da9063->chip_irq, ret); da9063->chip_irq, ret);
...@@ -182,8 +201,3 @@ int da9063_irq_init(struct da9063 *da9063) ...@@ -182,8 +201,3 @@ int da9063_irq_init(struct da9063 *da9063)
return 0; return 0;
} }
void da9063_irq_exit(struct da9063 *da9063)
{
regmap_del_irq_chip(da9063->chip_irq, da9063->regmap_irq);
}
...@@ -194,6 +194,7 @@ static bool dln2_transfer_complete(struct dln2_dev *dln2, struct urb *urb, ...@@ -194,6 +194,7 @@ static bool dln2_transfer_complete(struct dln2_dev *dln2, struct urb *urb,
struct device *dev = &dln2->interface->dev; struct device *dev = &dln2->interface->dev;
struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[handle]; struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[handle];
struct dln2_rx_context *rxc; struct dln2_rx_context *rxc;
unsigned long flags;
bool valid_slot = false; bool valid_slot = false;
if (rx_slot >= DLN2_MAX_RX_SLOTS) if (rx_slot >= DLN2_MAX_RX_SLOTS)
...@@ -201,18 +202,13 @@ static bool dln2_transfer_complete(struct dln2_dev *dln2, struct urb *urb, ...@@ -201,18 +202,13 @@ static bool dln2_transfer_complete(struct dln2_dev *dln2, struct urb *urb,
rxc = &rxs->slots[rx_slot]; rxc = &rxs->slots[rx_slot];
/* spin_lock_irqsave(&rxs->lock, flags);
* No need to disable interrupts as this lock is not taken in interrupt
* context elsewhere in this driver. This function (or its callers) are
* also not exported to other modules.
*/
spin_lock(&rxs->lock);
if (rxc->in_use && !rxc->urb) { if (rxc->in_use && !rxc->urb) {
rxc->urb = urb; rxc->urb = urb;
complete(&rxc->done); complete(&rxc->done);
valid_slot = true; valid_slot = true;
} }
spin_unlock(&rxs->lock); spin_unlock_irqrestore(&rxs->lock, flags);
out: out:
if (!valid_slot) if (!valid_slot)
......
...@@ -49,7 +49,7 @@ static struct regmap_config hi655x_regmap_config = { ...@@ -49,7 +49,7 @@ static struct regmap_config hi655x_regmap_config = {
.reg_bits = 32, .reg_bits = 32,
.reg_stride = HI655X_STRIDE, .reg_stride = HI655X_STRIDE,
.val_bits = 8, .val_bits = 8,
.max_register = HI655X_BUS_ADDR(0xFFF), .max_register = HI655X_BUS_ADDR(0x400) - HI655X_STRIDE,
}; };
static struct resource pwrkey_resources[] = { static struct resource pwrkey_resources[] = {
......
...@@ -178,6 +178,19 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { ...@@ -178,6 +178,19 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x31c2), (kernel_ulong_t)&bxt_info }, { PCI_VDEVICE(INTEL, 0x31c2), (kernel_ulong_t)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x31c4), (kernel_ulong_t)&bxt_info }, { PCI_VDEVICE(INTEL, 0x31c4), (kernel_ulong_t)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x31c6), (kernel_ulong_t)&bxt_info }, { PCI_VDEVICE(INTEL, 0x31c6), (kernel_ulong_t)&bxt_info },
/* ICL-LP */
{ PCI_VDEVICE(INTEL, 0x34a8), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x34a9), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x34aa), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0x34ab), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0x34c5), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x34c6), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x34c7), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x34e8), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x34e9), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x34ea), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x34eb), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x34fb), (kernel_ulong_t)&spt_info },
/* APL */ /* APL */
{ PCI_VDEVICE(INTEL, 0x5aac), (kernel_ulong_t)&apl_i2c_info }, { PCI_VDEVICE(INTEL, 0x5aac), (kernel_ulong_t)&apl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x5aae), (kernel_ulong_t)&apl_i2c_info }, { PCI_VDEVICE(INTEL, 0x5aae), (kernel_ulong_t)&apl_i2c_info },
......
...@@ -143,7 +143,7 @@ static struct platform_device *kempld_pdev; ...@@ -143,7 +143,7 @@ static struct platform_device *kempld_pdev;
static int kempld_create_platform_device(const struct dmi_system_id *id) static int kempld_create_platform_device(const struct dmi_system_id *id)
{ {
struct kempld_platform_data *pdata = id->driver_data; const struct kempld_platform_data *pdata = id->driver_data;
int ret; int ret;
kempld_pdev = platform_device_alloc("kempld", -1); kempld_pdev = platform_device_alloc("kempld", -1);
...@@ -259,7 +259,7 @@ EXPORT_SYMBOL_GPL(kempld_write32); ...@@ -259,7 +259,7 @@ EXPORT_SYMBOL_GPL(kempld_write32);
*/ */
void kempld_get_mutex(struct kempld_device_data *pld) void kempld_get_mutex(struct kempld_device_data *pld)
{ {
struct kempld_platform_data *pdata = dev_get_platdata(pld->dev); const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
mutex_lock(&pld->lock); mutex_lock(&pld->lock);
pdata->get_hardware_mutex(pld); pdata->get_hardware_mutex(pld);
...@@ -272,7 +272,7 @@ EXPORT_SYMBOL_GPL(kempld_get_mutex); ...@@ -272,7 +272,7 @@ EXPORT_SYMBOL_GPL(kempld_get_mutex);
*/ */
void kempld_release_mutex(struct kempld_device_data *pld) void kempld_release_mutex(struct kempld_device_data *pld)
{ {
struct kempld_platform_data *pdata = dev_get_platdata(pld->dev); const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
pdata->release_hardware_mutex(pld); pdata->release_hardware_mutex(pld);
mutex_unlock(&pld->lock); mutex_unlock(&pld->lock);
...@@ -290,7 +290,7 @@ EXPORT_SYMBOL_GPL(kempld_release_mutex); ...@@ -290,7 +290,7 @@ EXPORT_SYMBOL_GPL(kempld_release_mutex);
static int kempld_get_info(struct kempld_device_data *pld) static int kempld_get_info(struct kempld_device_data *pld)
{ {
int ret; int ret;
struct kempld_platform_data *pdata = dev_get_platdata(pld->dev); const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
char major, minor; char major, minor;
ret = pdata->get_info(pld); ret = pdata->get_info(pld);
...@@ -332,7 +332,7 @@ static int kempld_get_info(struct kempld_device_data *pld) ...@@ -332,7 +332,7 @@ static int kempld_get_info(struct kempld_device_data *pld)
*/ */
static int kempld_register_cells(struct kempld_device_data *pld) static int kempld_register_cells(struct kempld_device_data *pld)
{ {
struct kempld_platform_data *pdata = dev_get_platdata(pld->dev); const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
return pdata->register_cells(pld); return pdata->register_cells(pld);
} }
...@@ -444,7 +444,8 @@ static int kempld_detect_device(struct kempld_device_data *pld) ...@@ -444,7 +444,8 @@ static int kempld_detect_device(struct kempld_device_data *pld)
static int kempld_probe(struct platform_device *pdev) static int kempld_probe(struct platform_device *pdev)
{ {
struct kempld_platform_data *pdata = dev_get_platdata(&pdev->dev); const struct kempld_platform_data *pdata =
dev_get_platdata(&pdev->dev);
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct kempld_device_data *pld; struct kempld_device_data *pld;
struct resource *ioport; struct resource *ioport;
...@@ -476,7 +477,7 @@ static int kempld_probe(struct platform_device *pdev) ...@@ -476,7 +477,7 @@ static int kempld_probe(struct platform_device *pdev)
static int kempld_remove(struct platform_device *pdev) static int kempld_remove(struct platform_device *pdev)
{ {
struct kempld_device_data *pld = platform_get_drvdata(pdev); struct kempld_device_data *pld = platform_get_drvdata(pdev);
struct kempld_platform_data *pdata = dev_get_platdata(pld->dev); const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
sysfs_remove_group(&pld->dev->kobj, &pld_attr_group); sysfs_remove_group(&pld->dev->kobj, &pld_attr_group);
......
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0
/*
* I2C bus interface to Cirrus Logic Madera codecs
*
* Copyright (C) 2015-2018 Cirrus Logic
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; version 2.
*/
#include <linux/device.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/mfd/madera/core.h>
#include "madera.h"
static int madera_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct madera *madera;
const struct regmap_config *regmap_16bit_config = NULL;
const struct regmap_config *regmap_32bit_config = NULL;
const void *of_data;
unsigned long type;
const char *name;
int ret;
of_data = of_device_get_match_data(&i2c->dev);
if (of_data)
type = (unsigned long)of_data;
else
type = id->driver_data;
switch (type) {
case CS47L35:
if (IS_ENABLED(CONFIG_MFD_CS47L35)) {
regmap_16bit_config = &cs47l35_16bit_i2c_regmap;
regmap_32bit_config = &cs47l35_32bit_i2c_regmap;
}
break;
case CS47L85:
case WM1840:
if (IS_ENABLED(CONFIG_MFD_CS47L85)) {
regmap_16bit_config = &cs47l85_16bit_i2c_regmap;
regmap_32bit_config = &cs47l85_32bit_i2c_regmap;
}
break;
case CS47L90:
case CS47L91:
if (IS_ENABLED(CONFIG_MFD_CS47L90)) {
regmap_16bit_config = &cs47l90_16bit_i2c_regmap;
regmap_32bit_config = &cs47l90_32bit_i2c_regmap;
}
break;
default:
dev_err(&i2c->dev,
"Unknown Madera I2C device type %ld\n", type);
return -EINVAL;
}
name = madera_name_from_type(type);
if (!regmap_16bit_config) {
/* it's polite to say which codec isn't built into the kernel */
dev_err(&i2c->dev,
"Kernel does not include support for %s\n", name);
return -EINVAL;
}
madera = devm_kzalloc(&i2c->dev, sizeof(*madera), GFP_KERNEL);
if (!madera)
return -ENOMEM;
madera->regmap = devm_regmap_init_i2c(i2c, regmap_16bit_config);
if (IS_ERR(madera->regmap)) {
ret = PTR_ERR(madera->regmap);
dev_err(&i2c->dev,
"Failed to allocate 16-bit register map: %d\n", ret);
return ret;
}
madera->regmap_32bit = devm_regmap_init_i2c(i2c, regmap_32bit_config);
if (IS_ERR(madera->regmap_32bit)) {
ret = PTR_ERR(madera->regmap_32bit);
dev_err(&i2c->dev,
"Failed to allocate 32-bit register map: %d\n", ret);
return ret;
}
madera->type = type;
madera->type_name = name;
madera->dev = &i2c->dev;
madera->irq = i2c->irq;
return madera_dev_init(madera);
}
static int madera_i2c_remove(struct i2c_client *i2c)
{
struct madera *madera = dev_get_drvdata(&i2c->dev);
madera_dev_exit(madera);
return 0;
}
static const struct i2c_device_id madera_i2c_id[] = {
{ "cs47l35", CS47L35 },
{ "cs47l85", CS47L85 },
{ "cs47l90", CS47L90 },
{ "cs47l91", CS47L91 },
{ "wm1840", WM1840 },
{ }
};
MODULE_DEVICE_TABLE(i2c, madera_i2c_id);
static struct i2c_driver madera_i2c_driver = {
.driver = {
.name = "madera",
.pm = &madera_pm_ops,
.of_match_table = of_match_ptr(madera_of_match),
},
.probe = madera_i2c_probe,
.remove = madera_i2c_remove,
.id_table = madera_i2c_id,
};
module_i2c_driver(madera_i2c_driver);
MODULE_DESCRIPTION("Madera I2C bus interface");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_LICENSE("GPL v2");
// SPDX-License-Identifier: GPL-2.0
/*
* SPI bus interface to Cirrus Logic Madera codecs
*
* Copyright (C) 2015-2018 Cirrus Logic
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; version 2.
*/
#include <linux/device.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <linux/mfd/madera/core.h>
#include "madera.h"
static int madera_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
struct madera *madera;
const struct regmap_config *regmap_16bit_config = NULL;
const struct regmap_config *regmap_32bit_config = NULL;
const void *of_data;
unsigned long type;
const char *name;
int ret;
of_data = of_device_get_match_data(&spi->dev);
if (of_data)
type = (unsigned long)of_data;
else
type = id->driver_data;
switch (type) {
case CS47L35:
if (IS_ENABLED(CONFIG_MFD_CS47L35)) {
regmap_16bit_config = &cs47l35_16bit_spi_regmap;
regmap_32bit_config = &cs47l35_32bit_spi_regmap;
}
break;
case CS47L85:
case WM1840:
if (IS_ENABLED(CONFIG_MFD_CS47L85)) {
regmap_16bit_config = &cs47l85_16bit_spi_regmap;
regmap_32bit_config = &cs47l85_32bit_spi_regmap;
}
break;
case CS47L90:
case CS47L91:
if (IS_ENABLED(CONFIG_MFD_CS47L90)) {
regmap_16bit_config = &cs47l90_16bit_spi_regmap;
regmap_32bit_config = &cs47l90_32bit_spi_regmap;
}
break;
default:
dev_err(&spi->dev,
"Unknown Madera SPI device type %ld\n", type);
return -EINVAL;
}
name = madera_name_from_type(type);
if (!regmap_16bit_config) {
/* it's polite to say which codec isn't built into the kernel */
dev_err(&spi->dev,
"Kernel does not include support for %s\n", name);
return -EINVAL;
}
madera = devm_kzalloc(&spi->dev, sizeof(*madera), GFP_KERNEL);
if (!madera)
return -ENOMEM;
madera->regmap = devm_regmap_init_spi(spi, regmap_16bit_config);
if (IS_ERR(madera->regmap)) {
ret = PTR_ERR(madera->regmap);
dev_err(&spi->dev,
"Failed to allocate 16-bit register map: %d\n", ret);
return ret;
}
madera->regmap_32bit = devm_regmap_init_spi(spi, regmap_32bit_config);
if (IS_ERR(madera->regmap_32bit)) {
ret = PTR_ERR(madera->regmap_32bit);
dev_err(&spi->dev,
"Failed to allocate 32-bit register map: %d\n", ret);
return ret;
}
madera->type = type;
madera->type_name = name;
madera->dev = &spi->dev;
madera->irq = spi->irq;
return madera_dev_init(madera);
}
static int madera_spi_remove(struct spi_device *spi)
{
struct madera *madera = spi_get_drvdata(spi);
madera_dev_exit(madera);
return 0;
}
static const struct spi_device_id madera_spi_ids[] = {
{ "cs47l35", CS47L35 },
{ "cs47l85", CS47L85 },
{ "cs47l90", CS47L90 },
{ "cs47l91", CS47L91 },
{ "wm1840", WM1840 },
{ }
};
MODULE_DEVICE_TABLE(spi, madera_spi_ids);
static struct spi_driver madera_spi_driver = {
.driver = {
.name = "madera",
.pm = &madera_pm_ops,
.of_match_table = of_match_ptr(madera_of_match),
},
.probe = madera_spi_probe,
.remove = madera_spi_remove,
.id_table = madera_spi_ids,
};
module_spi_driver(madera_spi_driver);
MODULE_DESCRIPTION("Madera SPI bus interface");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_LICENSE("GPL v2");
/*
* MFD internals for Cirrus Logic Madera codecs
*
* Copyright 2015-2018 Cirrus Logic
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef MADERA_MFD_H
#define MADERA_MFD_H
#include <linux/of.h>
#include <linux/pm.h>
struct madera;
extern const struct dev_pm_ops madera_pm_ops;
extern const struct of_device_id madera_of_match[];
int madera_dev_init(struct madera *madera);
int madera_dev_exit(struct madera *madera);
const char *madera_name_from_type(enum madera_type type);
extern const struct regmap_config cs47l35_16bit_spi_regmap;
extern const struct regmap_config cs47l35_32bit_spi_regmap;
extern const struct regmap_config cs47l35_16bit_i2c_regmap;
extern const struct regmap_config cs47l35_32bit_i2c_regmap;
int cs47l35_patch(struct madera *madera);
extern const struct regmap_config cs47l85_16bit_spi_regmap;
extern const struct regmap_config cs47l85_32bit_spi_regmap;
extern const struct regmap_config cs47l85_16bit_i2c_regmap;
extern const struct regmap_config cs47l85_32bit_i2c_regmap;
int cs47l85_patch(struct madera *madera);
extern const struct regmap_config cs47l90_16bit_spi_regmap;
extern const struct regmap_config cs47l90_32bit_spi_regmap;
extern const struct regmap_config cs47l90_16bit_i2c_regmap;
extern const struct regmap_config cs47l90_32bit_i2c_regmap;
int cs47l90_patch(struct madera *madera);
#endif
...@@ -63,16 +63,6 @@ ...@@ -63,16 +63,6 @@
#define RAVE_SP_TX_BUFFER_SIZE \ #define RAVE_SP_TX_BUFFER_SIZE \
(RAVE_SP_STX_ETX_SIZE + 2 * RAVE_SP_RX_BUFFER_SIZE) (RAVE_SP_STX_ETX_SIZE + 2 * RAVE_SP_RX_BUFFER_SIZE)
#define RAVE_SP_BOOT_SOURCE_GET 0
#define RAVE_SP_BOOT_SOURCE_SET 1
#define RAVE_SP_RDU2_BOARD_TYPE_RMB 0
#define RAVE_SP_RDU2_BOARD_TYPE_DEB 1
#define RAVE_SP_BOOT_SOURCE_SD 0
#define RAVE_SP_BOOT_SOURCE_EMMC 1
#define RAVE_SP_BOOT_SOURCE_NOR 2
/** /**
* enum rave_sp_deframer_state - Possible state for de-framer * enum rave_sp_deframer_state - Possible state for de-framer
* *
...@@ -127,14 +117,44 @@ struct rave_sp_checksum { ...@@ -127,14 +117,44 @@ struct rave_sp_checksum {
void (*subroutine)(const u8 *, size_t, u8 *); void (*subroutine)(const u8 *, size_t, u8 *);
}; };
struct rave_sp_version {
u8 hardware;
__le16 major;
u8 minor;
u8 letter[2];
} __packed;
struct rave_sp_status {
struct rave_sp_version bootloader_version;
struct rave_sp_version firmware_version;
u16 rdu_eeprom_flag;
u16 dds_eeprom_flag;
u8 pic_flag;
u8 orientation;
u32 etc;
s16 temp[2];
u8 backlight_current[3];
u8 dip_switch;
u8 host_interrupt;
u16 voltage_28;
u8 i2c_device_status;
u8 power_status;
u8 general_status;
u8 deprecated1;
u8 power_led_status;
u8 deprecated2;
u8 periph_power_shutoff;
} __packed;
/** /**
* struct rave_sp_variant_cmds - Variant specific command routines * struct rave_sp_variant_cmds - Variant specific command routines
* *
* @translate: Generic to variant specific command mapping routine * @translate: Generic to variant specific command mapping routine
* * @get_status: Variant specific implementation of CMD_GET_STATUS
*/ */
struct rave_sp_variant_cmds { struct rave_sp_variant_cmds {
int (*translate)(enum rave_sp_command); int (*translate)(enum rave_sp_command);
int (*get_status)(struct rave_sp *sp, struct rave_sp_status *);
}; };
/** /**
...@@ -180,35 +200,6 @@ struct rave_sp { ...@@ -180,35 +200,6 @@ struct rave_sp {
const char *part_number_bootloader; const char *part_number_bootloader;
}; };
struct rave_sp_version {
u8 hardware;
__le16 major;
u8 minor;
u8 letter[2];
} __packed;
struct rave_sp_status {
struct rave_sp_version bootloader_version;
struct rave_sp_version firmware_version;
u16 rdu_eeprom_flag;
u16 dds_eeprom_flag;
u8 pic_flag;
u8 orientation;
u32 etc;
s16 temp[2];
u8 backlight_current[3];
u8 dip_switch;
u8 host_interrupt;
u16 voltage_28;
u8 i2c_device_status;
u8 power_status;
u8 general_status;
u8 deprecated1;
u8 power_led_status;
u8 deprecated2;
u8 periph_power_shutoff;
} __packed;
static bool rave_sp_id_is_event(u8 code) static bool rave_sp_id_is_event(u8 code)
{ {
return (code & 0xF0) == RAVE_SP_EVNT_BASE; return (code & 0xF0) == RAVE_SP_EVNT_BASE;
...@@ -641,10 +632,14 @@ static int rave_sp_default_cmd_translate(enum rave_sp_command command) ...@@ -641,10 +632,14 @@ static int rave_sp_default_cmd_translate(enum rave_sp_command command)
return 0x14; return 0x14;
case RAVE_SP_CMD_SW_WDT: case RAVE_SP_CMD_SW_WDT:
return 0x1C; return 0x1C;
case RAVE_SP_CMD_PET_WDT:
return 0x1D;
case RAVE_SP_CMD_RESET: case RAVE_SP_CMD_RESET:
return 0x1E; return 0x1E;
case RAVE_SP_CMD_RESET_REASON: case RAVE_SP_CMD_RESET_REASON:
return 0x1F; return 0x1F;
case RAVE_SP_CMD_RMB_EEPROM:
return 0x20;
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -666,18 +661,44 @@ static const char *devm_rave_sp_version(struct device *dev, ...@@ -666,18 +661,44 @@ static const char *devm_rave_sp_version(struct device *dev,
version->letter[1]); version->letter[1]);
} }
static int rave_sp_get_status(struct rave_sp *sp) static int rave_sp_rdu1_get_status(struct rave_sp *sp,
struct rave_sp_status *status)
{ {
struct device *dev = &sp->serdev->dev;
u8 cmd[] = { u8 cmd[] = {
[0] = RAVE_SP_CMD_STATUS, [0] = RAVE_SP_CMD_STATUS,
[1] = 0 [1] = 0
}; };
return rave_sp_exec(sp, cmd, sizeof(cmd), status, sizeof(*status));
}
static int rave_sp_emulated_get_status(struct rave_sp *sp,
struct rave_sp_status *status)
{
u8 cmd[] = {
[0] = RAVE_SP_CMD_GET_FIRMWARE_VERSION,
[1] = 0,
};
int ret;
ret = rave_sp_exec(sp, cmd, sizeof(cmd), &status->firmware_version,
sizeof(status->firmware_version));
if (ret)
return ret;
cmd[0] = RAVE_SP_CMD_GET_BOOTLOADER_VERSION;
return rave_sp_exec(sp, cmd, sizeof(cmd), &status->bootloader_version,
sizeof(status->bootloader_version));
}
static int rave_sp_get_status(struct rave_sp *sp)
{
struct device *dev = &sp->serdev->dev;
struct rave_sp_status status; struct rave_sp_status status;
const char *version; const char *version;
int ret; int ret;
ret = rave_sp_exec(sp, cmd, sizeof(cmd), &status, sizeof(status)); ret = sp->variant->cmd.get_status(sp, &status);
if (ret) if (ret)
return ret; return ret;
...@@ -707,9 +728,10 @@ static const struct rave_sp_checksum rave_sp_checksum_ccitt = { ...@@ -707,9 +728,10 @@ static const struct rave_sp_checksum rave_sp_checksum_ccitt = {
}; };
static const struct rave_sp_variant rave_sp_legacy = { static const struct rave_sp_variant rave_sp_legacy = {
.checksum = &rave_sp_checksum_8b2c, .checksum = &rave_sp_checksum_ccitt,
.cmd = { .cmd = {
.translate = rave_sp_default_cmd_translate, .translate = rave_sp_default_cmd_translate,
.get_status = rave_sp_emulated_get_status,
}, },
}; };
...@@ -717,6 +739,7 @@ static const struct rave_sp_variant rave_sp_rdu1 = { ...@@ -717,6 +739,7 @@ static const struct rave_sp_variant rave_sp_rdu1 = {
.checksum = &rave_sp_checksum_8b2c, .checksum = &rave_sp_checksum_8b2c,
.cmd = { .cmd = {
.translate = rave_sp_rdu1_cmd_translate, .translate = rave_sp_rdu1_cmd_translate,
.get_status = rave_sp_rdu1_get_status,
}, },
}; };
...@@ -724,6 +747,7 @@ static const struct rave_sp_variant rave_sp_rdu2 = { ...@@ -724,6 +747,7 @@ static const struct rave_sp_variant rave_sp_rdu2 = {
.checksum = &rave_sp_checksum_ccitt, .checksum = &rave_sp_checksum_ccitt,
.cmd = { .cmd = {
.translate = rave_sp_rdu2_cmd_translate, .translate = rave_sp_rdu2_cmd_translate,
.get_status = rave_sp_emulated_get_status,
}, },
}; };
...@@ -776,6 +800,13 @@ static int rave_sp_probe(struct serdev_device *serdev) ...@@ -776,6 +800,13 @@ static int rave_sp_probe(struct serdev_device *serdev)
return ret; return ret;
serdev_device_set_baudrate(serdev, baud); serdev_device_set_baudrate(serdev, baud);
serdev_device_set_flow_control(serdev, false);
ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE);
if (ret) {
dev_err(dev, "Failed to set parity\n");
return ret;
}
ret = rave_sp_get_status(sp); ret = rave_sp_get_status(sp);
if (ret) { if (ret) {
......
This diff is collapsed.
...@@ -146,6 +146,7 @@ static const struct of_device_id sec_dt_match[] = { ...@@ -146,6 +146,7 @@ static const struct of_device_id sec_dt_match[] = {
/* Sentinel */ /* Sentinel */
}, },
}; };
MODULE_DEVICE_TABLE(of, sec_dt_match);
#endif #endif
static bool s2mpa01_volatile(struct device *dev, unsigned int reg) static bool s2mpa01_volatile(struct device *dev, unsigned int reg)
......
...@@ -715,6 +715,7 @@ sm501_create_subdev(struct sm501_devdata *sm, char *name, ...@@ -715,6 +715,7 @@ sm501_create_subdev(struct sm501_devdata *sm, char *name,
smdev->pdev.name = name; smdev->pdev.name = name;
smdev->pdev.id = sm->pdev_id; smdev->pdev.id = sm->pdev_id;
smdev->pdev.dev.parent = sm->dev; smdev->pdev.dev.parent = sm->dev;
smdev->pdev.dev.coherent_dma_mask = 0xffffffff;
if (res_count) { if (res_count) {
smdev->pdev.resource = (struct resource *)(smdev+1); smdev->pdev.resource = (struct resource *)(smdev+1);
......
...@@ -209,14 +209,13 @@ static int ti_tscadc_probe(struct platform_device *pdev) ...@@ -209,14 +209,13 @@ static int ti_tscadc_probe(struct platform_device *pdev)
* The TSC_ADC_SS controller design assumes the OCP clock is * The TSC_ADC_SS controller design assumes the OCP clock is
* at least 6x faster than the ADC clock. * at least 6x faster than the ADC clock.
*/ */
clk = clk_get(&pdev->dev, "adc_tsc_fck"); clk = devm_clk_get(&pdev->dev, "adc_tsc_fck");
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(&pdev->dev, "failed to get TSC fck\n"); dev_err(&pdev->dev, "failed to get TSC fck\n");
err = PTR_ERR(clk); err = PTR_ERR(clk);
goto err_disable_clk; goto err_disable_clk;
} }
clock_rate = clk_get_rate(clk); clock_rate = clk_get_rate(clk);
clk_put(clk);
tscadc->clk_div = clock_rate / ADC_CLK; tscadc->clk_div = clock_rate / ADC_CLK;
/* TSCADC_CLKDIV needs to be configured to the value minus 1 */ /* TSCADC_CLKDIV needs to be configured to the value minus 1 */
......
This diff is collapsed.
...@@ -361,6 +361,7 @@ source "drivers/pinctrl/vt8500/Kconfig" ...@@ -361,6 +361,7 @@ source "drivers/pinctrl/vt8500/Kconfig"
source "drivers/pinctrl/mediatek/Kconfig" source "drivers/pinctrl/mediatek/Kconfig"
source "drivers/pinctrl/zte/Kconfig" source "drivers/pinctrl/zte/Kconfig"
source "drivers/pinctrl/meson/Kconfig" source "drivers/pinctrl/meson/Kconfig"
source "drivers/pinctrl/cirrus/Kconfig"
config PINCTRL_XWAY config PINCTRL_XWAY
bool bool
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment