- Core Frameworks

- Add support for a "resource managed strongly uncachable ioremap" call
    - Provide a collection of MFD helper macros
    - Remove mfd_clone_cell() from MFD core
    - Add NULL de-reference protection in MFD core
    - Remove superfluous function fd_platform_add_cell() from MFD core
    - Honour Device Tree's request to disable a device
 
  - New Drivers
    - Add support for MediaTek MT6323 PMIC
 
  - New Device Support
    - Add support for Gemini Lake to Intel LPSS PCI
    - Add support for Cherry Trail Crystal Cover PMIC to Intel SoC PMIC CRC
    - Add support for PM{I}8950 to Qualcomm SPMI PMIC
    - Add support for U8420 to ST-Ericsson DB8500
    - Add support for Comet Lake PCH-H to Intel LPSS PCI
 
  - New Functionality
    - Add support for requested supply clocks; madera-core
 
  - Fix-ups
    - Lower interrupt priority; rk808
    - Use provided helpers (macros, group functions, defines); rk808,
 		ipaq-micro, ab8500-core, db8500-prcmu, mt6397-core, cs5535-mfd
    - Only allocate IRQs on request; max77620
    - Use simplified API; arizona-core
    - Remove redundant and/or duplicated code; wm8998-tables, arizona, syscon
    - Device Tree binding fix-ups; madera, max77650, max77693
    - Remove mfd_cell->id abuse hack; cs5535-mfd
    - Remove only user of mfd_clone_cell(); cs5535-mfd
    - Make resources static; rohm-bd70528
 
  - Bug Fixes
    - Fix product ID for RK818; rk808
    - Fix Power Key; rk808
    - Fix booting on the BananaPi; mt6397-core
    - Endian fix-ups; twl.h
    - Fix static error checker warnings; ti_am335x_tscadc
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEdrbJNaO+IJqU8IdIUa+KL4f8d2EFAl3f2k4ACgkQUa+KL4f8
 d2GmohAAluAT7hhURCf2HECsbVpeLH5i5UahRTCAlyIqeAiOjGEBGdIT2fYM1B+3
 daqj3XiiLqvlnT5FZc4Fw5gR9Nu6Oe+Fo+6p6NnAu7CIt+x9RXOTB5LLXYYKICZK
 c32SnsSbRQwtzu83d3CjlfQRUZh66fJksWVPnOBkenaR7HaQlujKydBAk3kkLygZ
 3GGTzjTXakl/53XJLRNn2wVVEG2gCicZwWxmWYW2000PFWo1upCeJRcwHBOXyy1I
 oh+KNp28gVQLT3pOte4TZEO3GNacMMs5DvA0hj2j7j+nH5FOryEPjUNbrqkcR+9T
 aquGbgYWgfJrW9UJhgNVsn754y5sgZ48Q20533AICMDfy3JTzfn91pX5q8mVFaPl
 Kf4cTVAau7kUCVxrXWuOG2fG2r7BjRABKU5ODDsGWmfWQNdktvLvHJI4j97ct0xj
 neBijJya70woV1o40v5yTmcUcc7hGEoKXuRWslxNK3K+nQkgRKMKgY4dm3jBeSmD
 lmBrjtjT0gcNl6+bOOn6IXn5k3sxWUwa799LUDaR5oHj6kB0LkIqz3h6UlOBryKO
 iQ2xXXCf/gAlkL75SW1rjYBHWkMkswgigppcbw2HB9tMqGL2LtHtgIli8CfGz1vs
 BzwxOQRvMK+4rG0qNHbocXJK2O4PduTxMXtBDiVK/tXrHaNLs7I=
 =mugH
 -----END PGP SIGNATURE-----

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

Pull MFD updates from Lee Jones:
 "Core Frameworks:
   - Add support for a "resource managed strongly uncachable ioremap"
     call
   - Provide a collection of MFD helper macros
   - Remove mfd_clone_cell() from MFD core
   - Add NULL de-reference protection in MFD core
   - Remove superfluous function fd_platform_add_cell() from MFD core
   - Honour Device Tree's request to disable a device

  New Drivers:
   - Add support for MediaTek MT6323 PMIC

  New Device Support:
   - Add support for Gemini Lake to Intel LPSS PCI
   - Add support for Cherry Trail Crystal Cover PMIC to Intel SoC PMIC
     CRC
   - Add support for PM{I}8950 to Qualcomm SPMI PMIC
   - Add support for U8420 to ST-Ericsson DB8500
   - Add support for Comet Lake PCH-H to Intel LPSS PCI

  New Functionality:
   - Add support for requested supply clocks; madera-core

  Fix-ups:
   - Lower interrupt priority; rk808
   - Use provided helpers (macros, group functions, defines); rk808,
     ipaq-micro, ab8500-core, db8500-prcmu, mt6397-core, cs5535-mfd
   - Only allocate IRQs on request; max77620
   - Use simplified API; arizona-core
   - Remove redundant and/or duplicated code; wm8998-tables, arizona,
     syscon
   - Device Tree binding fix-ups; madera, max77650, max77693
   - Remove mfd_cell->id abuse hack; cs5535-mfd
   - Remove only user of mfd_clone_cell(); cs5535-mfd
   - Make resources static; rohm-bd70528

  Bug Fixes:
   - Fix product ID for RK818; rk808
   - Fix Power Key; rk808
   - Fix booting on the BananaPi; mt6397-core
   - Endian fix-ups; twl.h
   - Fix static error checker warnings; ti_am335x_tscadc"

* tag 'mfd-next-5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (47 commits)
  Revert "mfd: syscon: Set name of regmap_config"
  mfd: ti_am335x_tscadc: Fix static checker warning
  mfd: bd70528: Staticize bit value definitions
  mfd: mfd-core: Honour Device Tree's request to disable a child-device
  dt-bindings: mfd: max77693: Fix missing curly brace
  mfd: intel-lpss: Add Intel Comet Lake PCH-H PCI IDs
  mfd: db8500-prcmu: Support U8420-sysclk firmware
  dt-bindings: mfd: max77650: Convert the binding document to yaml
  mfd: mfd-core: Move pdev->mfd_cell creation back into mfd_add_device()
  mfd: mfd-core: Remove usage counting for .{en,dis}able() call-backs
  x86: olpc-xo1-sci: Remove invocation of MFD's .enable()/.disable() call-backs
  x86: olpc-xo1-pm: Remove invocation of MFD's .enable()/.disable() call-backs
  mfd: mfd-core: Remove mfd_clone_cell()
  mfd: mfd-core: Protect against NULL call-back function pointer
  mfd: cs5535-mfd: Register clients using their own dedicated MFD cell entries
  mfd: cs5535-mfd: Request shared IO regions centrally
  mfd: cs5535-mfd: Remove mfd_cell->id hack
  mfd: cs5535-mfd: Use PLATFORM_DEVID_* defines and tidy error message
  mfd: intel_soc_pmic_crc: Add "cht_crystal_cove_pmic" cell to CHT cells
  mfd: madera: Add support for requesting the supply clocks
  ...
This commit is contained in:
Linus Torvalds 2019-12-01 16:16:31 -08:00
commit 37323918ca
45 changed files with 734 additions and 542 deletions

View File

@ -67,6 +67,14 @@ Optional properties:
As defined in bindings/gpio.txt. As defined in bindings/gpio.txt.
Although optional, it is strongly recommended to use a hardware reset Although optional, it is strongly recommended to use a hardware reset
- clocks: Should reference the clocks supplied on MCLK1, MCLK2 and MCLK3
- clock-names: May contain up to three strings:
"mclk1" for the clock supplied on MCLK1, recommended to be a high
quality audio reference clock
"mclk2" for the clock supplied on MCLK2, required to be an always on
32k clock
"mclk3" for the clock supplied on MCLK3
- MICBIASx : Initial data for the MICBIAS regulators, as covered in - MICBIASx : Initial data for the MICBIAS regulators, as covered in
Documentation/devicetree/bindings/regulator/regulator.txt. Documentation/devicetree/bindings/regulator/regulator.txt.
One for each MICBIAS generator (MICBIAS1, MICBIAS2, ...) One for each MICBIAS generator (MICBIAS1, MICBIAS2, ...)

View File

@ -1,46 +0,0 @@
MAX77650 ultra low-power PMIC from Maxim Integrated.
Required properties:
-------------------
- compatible: Must be "maxim,max77650"
- reg: I2C device address.
- interrupts: The interrupt on the parent the controller is
connected to.
- interrupt-controller: Marks the device node as an interrupt controller.
- #interrupt-cells: Must be <2>.
- gpio-controller: Marks the device node as a gpio controller.
- #gpio-cells: Must be <2>. The first cell is the pin number and
the second cell is used to specify the gpio active
state.
Optional properties:
--------------------
gpio-line-names: Single string containing the name of the GPIO line.
The GPIO-controller module is represented as part of the top-level PMIC
node. The device exposes a single GPIO line.
For device-tree bindings of other sub-modules (regulator, power supply,
LEDs and onkey) refer to the binding documents under the respective
sub-system directories.
For more details on GPIO bindings, please refer to the generic GPIO DT
binding document <devicetree/bindings/gpio/gpio.txt>.
Example:
--------
pmic@48 {
compatible = "maxim,max77650";
reg = <0x48>;
interrupt-controller;
interrupt-parent = <&gpio2>;
#interrupt-cells = <2>;
interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
gpio-controller;
#gpio-cells = <2>;
gpio-line-names = "max77650-charger";
};

View File

@ -0,0 +1,149 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/max77650.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MAX77650 ultra low-power PMIC from Maxim Integrated.
maintainers:
- Bartosz Golaszewski <bgolaszewski@baylibre.com>
description: |
MAX77650 is an ultra-low power PMIC providing battery charging and power
supply for low-power IoT and wearable applications.
The GPIO-controller module is represented as part of the top-level PMIC
node. The device exposes a single GPIO line.
For device-tree bindings of other sub-modules (regulator, power supply,
LEDs and onkey) refer to the binding documents under the respective
sub-system directories.
properties:
compatible:
const: maxim,max77650
reg:
description:
I2C device address.
maxItems: 1
interrupts:
maxItems: 1
interrupt-controller: true
"#interrupt-cells":
const: 2
description:
The first cell is the IRQ number, the second cell is the trigger type.
gpio-controller: true
"#gpio-cells":
const: 2
description:
The first cell is the pin number and the second cell is used to specify
the gpio active state.
gpio-line-names:
maxItems: 1
description:
Single string containing the name of the GPIO line.
regulators:
$ref: ../regulator/max77650-regulator.yaml
charger:
$ref: ../power/supply/max77650-charger.yaml
leds:
$ref: ../leds/leds-max77650.yaml
onkey:
$ref: ../input/max77650-onkey.yaml
required:
- compatible
- reg
- interrupts
- interrupt-controller
- "#interrupt-cells"
- gpio-controller
- "#gpio-cells"
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/input/linux-event-codes.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
pmic@48 {
compatible = "maxim,max77650";
reg = <0x48>;
interrupt-controller;
interrupt-parent = <&gpio2>;
#interrupt-cells = <2>;
interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
gpio-controller;
#gpio-cells = <2>;
gpio-line-names = "max77650-charger";
regulators {
compatible = "maxim,max77650-regulator";
max77650_ldo: regulator@0 {
regulator-compatible = "ldo";
regulator-name = "max77650-ldo";
regulator-min-microvolt = <1350000>;
regulator-max-microvolt = <2937500>;
};
max77650_sbb0: regulator@1 {
regulator-compatible = "sbb0";
regulator-name = "max77650-sbb0";
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1587500>;
};
};
charger {
compatible = "maxim,max77650-charger";
input-voltage-min-microvolt = <4200000>;
input-current-limit-microamp = <285000>;
};
leds {
compatible = "maxim,max77650-led";
#address-cells = <1>;
#size-cells = <0>;
led@0 {
reg = <0>;
label = "blue:usr0";
};
led@1 {
reg = <1>;
label = "red:usr1";
linux,default-trigger = "heartbeat";
};
led@2 {
reg = <2>;
label = "green:usr2";
};
};
onkey {
compatible = "maxim,max77650-onkey";
linux,code = <KEY_END>;
maxim,onkey-slide;
};
};
};

View File

@ -175,6 +175,7 @@ Example:
maxim,thermal-regulation-celsius = <75>; maxim,thermal-regulation-celsius = <75>;
maxim,battery-overcurrent-microamp = <3000000>; maxim,battery-overcurrent-microamp = <3000000>;
maxim,charge-input-threshold-microvolt = <4300000>; maxim,charge-input-threshold-microvolt = <4300000>;
};
led { led {
compatible = "maxim,max77693-led"; compatible = "maxim,max77693-led";

View File

@ -29,6 +29,8 @@ Required properties:
"qcom,pm8916", "qcom,pm8916",
"qcom,pm8004", "qcom,pm8004",
"qcom,pm8909", "qcom,pm8909",
"qcom,pm8950",
"qcom,pmi8950",
"qcom,pm8998", "qcom,pm8998",
"qcom,pmi8998", "qcom,pmi8998",
"qcom,pm8005", "qcom,pm8005",

View File

@ -0,0 +1,29 @@
Device-Tree bindings for MediaTek PMIC based RTC
MediaTek PMIC based RTC is an independent function of MediaTek PMIC that works
as a type of multi-function device (MFD). The RTC can be configured and set up
with PMIC wrapper bus which is a common resource shared with the other
functions found on the same PMIC.
For MediaTek PMIC MFD bindings, see:
../mfd/mt6397.txt
For MediaTek PMIC wrapper bus bindings, see:
../soc/mediatek/pwrap.txt
Required properties:
- compatible: Should be one of follows
"mediatek,mt6323-rtc": for MT6323 PMIC
"mediatek,mt6397-rtc": for MT6397 PMIC
Example:
pmic {
compatible = "mediatek,mt6323";
...
rtc {
compatible = "mediatek,mt6323-rtc";
};
};

View File

@ -314,6 +314,7 @@ IOMAP
devm_ioport_unmap() devm_ioport_unmap()
devm_ioremap() devm_ioremap()
devm_ioremap_nocache() devm_ioremap_nocache()
devm_ioremap_uc()
devm_ioremap_wc() devm_ioremap_wc()
devm_ioremap_resource() : checks resource, requests memory region, ioremaps devm_ioremap_resource() : checks resource, requests memory region, ioremaps
devm_ioremap_resource_wc() devm_ioremap_resource_wc()

View File

@ -10396,6 +10396,13 @@ S: Maintained
F: drivers/net/dsa/mt7530.* F: drivers/net/dsa/mt7530.*
F: net/dsa/tag_mtk.c F: net/dsa/tag_mtk.c
MEDIATEK BOARD LEVEL SHUTDOWN DRIVERS
M: Sean Wang <sean.wang@mediatek.com>
L: linux-pm@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/power/reset/mt6323-poweroff.txt
F: drivers/power/reset/mt6323-poweroff.c
MEDIATEK JPEG DRIVER MEDIATEK JPEG DRIVER
M: Rick Chang <rick.chang@mediatek.com> M: Rick Chang <rick.chang@mediatek.com>
M: Bin Liu <bin.liu@mediatek.com> M: Bin Liu <bin.liu@mediatek.com>

View File

@ -84,6 +84,7 @@ static void __init ux500_init_irq(void)
struct resource r; struct resource r;
irqchip_init(); irqchip_init();
prcmu_early_init();
np = of_find_compatible_node(NULL, NULL, "stericsson,db8500-prcmu"); np = of_find_compatible_node(NULL, NULL, "stericsson,db8500-prcmu");
of_address_to_resource(np, 0, &r); of_address_to_resource(np, 0, &r);
of_node_put(np); of_node_put(np);
@ -91,7 +92,6 @@ static void __init ux500_init_irq(void)
pr_err("could not find PRCMU base resource\n"); pr_err("could not find PRCMU base resource\n");
return; return;
} }
prcmu_early_init(r.start, r.end-r.start);
ux500_pm_init(r.start, r.end-r.start); ux500_pm_init(r.start, r.end-r.start);
/* Unlock before init */ /* Unlock before init */

View File

@ -407,6 +407,7 @@ static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
} }
#define ioremap_nocache(X,Y) ioremap((X),(Y)) #define ioremap_nocache(X,Y) ioremap((X),(Y))
#define ioremap_uc(X,Y) ioremap((X),(Y))
#define ioremap_wc(X,Y) ioremap((X),(Y)) #define ioremap_wc(X,Y) ioremap((X),(Y))
#define ioremap_wt(X,Y) ioremap((X),(Y)) #define ioremap_wt(X,Y) ioremap((X),(Y))

View File

@ -12,7 +12,6 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/mfd/core.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include <linux/olpc-ec.h> #include <linux/olpc-ec.h>
@ -120,16 +119,11 @@ static const struct platform_suspend_ops xo1_suspend_ops = {
static int xo1_pm_probe(struct platform_device *pdev) static int xo1_pm_probe(struct platform_device *pdev)
{ {
struct resource *res; struct resource *res;
int err;
/* don't run on non-XOs */ /* don't run on non-XOs */
if (!machine_is_olpc()) if (!machine_is_olpc())
return -ENODEV; return -ENODEV;
err = mfd_cell_enable(pdev);
if (err)
return err;
res = platform_get_resource(pdev, IORESOURCE_IO, 0); res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!res) { if (!res) {
dev_err(&pdev->dev, "can't fetch device resource info\n"); dev_err(&pdev->dev, "can't fetch device resource info\n");
@ -152,8 +146,6 @@ static int xo1_pm_probe(struct platform_device *pdev)
static int xo1_pm_remove(struct platform_device *pdev) static int xo1_pm_remove(struct platform_device *pdev)
{ {
mfd_cell_disable(pdev);
if (strcmp(pdev->name, "cs5535-pms") == 0) if (strcmp(pdev->name, "cs5535-pms") == 0)
pms_base = 0; pms_base = 0;
else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0) else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)

View File

@ -15,7 +15,6 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/pm_wakeup.h> #include <linux/pm_wakeup.h>
#include <linux/mfd/core.h>
#include <linux/power_supply.h> #include <linux/power_supply.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
@ -537,10 +536,6 @@ static int xo1_sci_probe(struct platform_device *pdev)
if (!machine_is_olpc()) if (!machine_is_olpc())
return -ENODEV; return -ENODEV;
r = mfd_cell_enable(pdev);
if (r)
return r;
res = platform_get_resource(pdev, IORESOURCE_IO, 0); res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!res) { if (!res) {
dev_err(&pdev->dev, "can't fetch device resource info\n"); dev_err(&pdev->dev, "can't fetch device resource info\n");
@ -605,7 +600,6 @@ static int xo1_sci_probe(struct platform_device *pdev)
static int xo1_sci_remove(struct platform_device *pdev) static int xo1_sci_remove(struct platform_device *pdev)
{ {
mfd_cell_disable(pdev);
free_irq(sci_irq, pdev); free_irq(sci_irq, pdev);
cancel_work_sync(&sci_work); cancel_work_sync(&sci_work);
free_ec_sci(); free_ec_sci();

View File

@ -610,107 +610,53 @@ int ab8500_suspend(struct ab8500 *ab8500)
} }
static const struct mfd_cell ab8500_bm_devs[] = { static const struct mfd_cell ab8500_bm_devs[] = {
{ OF_MFD_CELL("ab8500-charger", NULL, &ab8500_bm_data,
.name = "ab8500-charger", sizeof(ab8500_bm_data), 0, "stericsson,ab8500-charger"),
.of_compatible = "stericsson,ab8500-charger", OF_MFD_CELL("ab8500-btemp", NULL, &ab8500_bm_data,
.platform_data = &ab8500_bm_data, sizeof(ab8500_bm_data), 0, "stericsson,ab8500-btemp"),
.pdata_size = sizeof(ab8500_bm_data), OF_MFD_CELL("ab8500-fg", NULL, &ab8500_bm_data,
}, sizeof(ab8500_bm_data), 0, "stericsson,ab8500-fg"),
{ OF_MFD_CELL("ab8500-chargalg", NULL, &ab8500_bm_data,
.name = "ab8500-btemp", sizeof(ab8500_bm_data), 0, "stericsson,ab8500-chargalg"),
.of_compatible = "stericsson,ab8500-btemp",
.platform_data = &ab8500_bm_data,
.pdata_size = sizeof(ab8500_bm_data),
},
{
.name = "ab8500-fg",
.of_compatible = "stericsson,ab8500-fg",
.platform_data = &ab8500_bm_data,
.pdata_size = sizeof(ab8500_bm_data),
},
{
.name = "ab8500-chargalg",
.of_compatible = "stericsson,ab8500-chargalg",
.platform_data = &ab8500_bm_data,
.pdata_size = sizeof(ab8500_bm_data),
},
}; };
static const struct mfd_cell ab8500_devs[] = { static const struct mfd_cell ab8500_devs[] = {
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
{ OF_MFD_CELL("ab8500-debug",
.name = "ab8500-debug", NULL, NULL, 0, 0, "stericsson,ab8500-debug"),
.of_compatible = "stericsson,ab8500-debug",
},
#endif #endif
{ OF_MFD_CELL("ab8500-sysctrl",
.name = "ab8500-sysctrl", NULL, NULL, 0, 0, "stericsson,ab8500-sysctrl"),
.of_compatible = "stericsson,ab8500-sysctrl", OF_MFD_CELL("ab8500-ext-regulator",
}, NULL, NULL, 0, 0, "stericsson,ab8500-ext-regulator"),
{ OF_MFD_CELL("ab8500-regulator",
.name = "ab8500-ext-regulator", NULL, NULL, 0, 0, "stericsson,ab8500-regulator"),
.of_compatible = "stericsson,ab8500-ext-regulator", OF_MFD_CELL("abx500-clk",
}, NULL, NULL, 0, 0, "stericsson,abx500-clk"),
{ OF_MFD_CELL("ab8500-gpadc",
.name = "ab8500-regulator", NULL, NULL, 0, 0, "stericsson,ab8500-gpadc"),
.of_compatible = "stericsson,ab8500-regulator", OF_MFD_CELL("ab8500-rtc",
}, NULL, NULL, 0, 0, "stericsson,ab8500-rtc"),
{ OF_MFD_CELL("ab8500-acc-det",
.name = "ab8500-clk", NULL, NULL, 0, 0, "stericsson,ab8500-acc-det"),
.of_compatible = "stericsson,ab8500-clk", OF_MFD_CELL("ab8500-poweron-key",
}, NULL, NULL, 0, 0, "stericsson,ab8500-poweron-key"),
{ OF_MFD_CELL("ab8500-pwm",
.name = "ab8500-gpadc", NULL, NULL, 0, 1, "stericsson,ab8500-pwm"),
.of_compatible = "stericsson,ab8500-gpadc", OF_MFD_CELL("ab8500-pwm",
}, NULL, NULL, 0, 2, "stericsson,ab8500-pwm"),
{ OF_MFD_CELL("ab8500-pwm",
.name = "ab8500-rtc", NULL, NULL, 0, 3, "stericsson,ab8500-pwm"),
.of_compatible = "stericsson,ab8500-rtc", OF_MFD_CELL("ab8500-denc",
}, NULL, NULL, 0, 0, "stericsson,ab8500-denc"),
{ OF_MFD_CELL("pinctrl-ab8500",
.name = "ab8500-acc-det", NULL, NULL, 0, 0, "stericsson,ab8500-gpio"),
.of_compatible = "stericsson,ab8500-acc-det", OF_MFD_CELL("abx500-temp",
}, NULL, NULL, 0, 0, "stericsson,abx500-temp"),
{ OF_MFD_CELL("ab8500-usb",
NULL, NULL, 0, 0, "stericsson,ab8500-usb"),
.name = "ab8500-poweron-key", OF_MFD_CELL("ab8500-codec",
.of_compatible = "stericsson,ab8500-poweron-key", NULL, NULL, 0, 0, "stericsson,ab8500-codec"),
},
{
.name = "ab8500-pwm",
.of_compatible = "stericsson,ab8500-pwm",
.id = 1,
},
{
.name = "ab8500-pwm",
.of_compatible = "stericsson,ab8500-pwm",
.id = 2,
},
{
.name = "ab8500-pwm",
.of_compatible = "stericsson,ab8500-pwm",
.id = 3,
},
{
.name = "ab8500-denc",
.of_compatible = "stericsson,ab8500-denc",
},
{
.name = "pinctrl-ab8500",
.of_compatible = "stericsson,ab8500-gpio",
},
{
.name = "abx500-temp",
.of_compatible = "stericsson,abx500-temp",
},
{
.name = "ab8500-usb",
.of_compatible = "stericsson,ab8500-usb",
},
{
.name = "ab8500-codec",
.of_compatible = "stericsson,ab8500-codec",
},
}; };
static const struct mfd_cell ab9540_devs[] = { static const struct mfd_cell ab9540_devs[] = {

View File

@ -814,11 +814,7 @@ static int arizona_of_get_core_pdata(struct arizona *arizona)
int ret, i; int ret, i;
/* Handle old non-standard DT binding */ /* Handle old non-standard DT binding */
pdata->reset = devm_gpiod_get_from_of_node(arizona->dev, pdata->reset = devm_gpiod_get(arizona->dev, "wlf,reset", GPIOD_OUT_LOW);
arizona->dev->of_node,
"wlf,reset", 0,
GPIOD_OUT_LOW,
"arizona /RESET");
if (IS_ERR(pdata->reset)) { if (IS_ERR(pdata->reset)) {
ret = PTR_ERR(pdata->reset); ret = PTR_ERR(pdata->reset);

View File

@ -27,121 +27,106 @@ enum cs5535_mfd_bars {
NR_BARS, NR_BARS,
}; };
static int cs5535_mfd_res_enable(struct platform_device *pdev)
{
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!res) {
dev_err(&pdev->dev, "can't fetch device resource info\n");
return -EIO;
}
if (!request_region(res->start, resource_size(res), DRV_NAME)) {
dev_err(&pdev->dev, "can't request region\n");
return -EIO;
}
return 0;
}
static int cs5535_mfd_res_disable(struct platform_device *pdev)
{
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!res) {
dev_err(&pdev->dev, "can't fetch device resource info\n");
return -EIO;
}
release_region(res->start, resource_size(res));
return 0;
}
static struct resource cs5535_mfd_resources[NR_BARS]; static struct resource cs5535_mfd_resources[NR_BARS];
static struct mfd_cell cs5535_mfd_cells[] = { static struct mfd_cell cs5535_mfd_cells[] = {
{ {
.id = SMB_BAR,
.name = "cs5535-smb", .name = "cs5535-smb",
.num_resources = 1, .num_resources = 1,
.resources = &cs5535_mfd_resources[SMB_BAR], .resources = &cs5535_mfd_resources[SMB_BAR],
}, },
{ {
.id = GPIO_BAR,
.name = "cs5535-gpio", .name = "cs5535-gpio",
.num_resources = 1, .num_resources = 1,
.resources = &cs5535_mfd_resources[GPIO_BAR], .resources = &cs5535_mfd_resources[GPIO_BAR],
}, },
{ {
.id = MFGPT_BAR,
.name = "cs5535-mfgpt", .name = "cs5535-mfgpt",
.num_resources = 1, .num_resources = 1,
.resources = &cs5535_mfd_resources[MFGPT_BAR], .resources = &cs5535_mfd_resources[MFGPT_BAR],
}, },
{ {
.id = PMS_BAR,
.name = "cs5535-pms", .name = "cs5535-pms",
.num_resources = 1, .num_resources = 1,
.resources = &cs5535_mfd_resources[PMS_BAR], .resources = &cs5535_mfd_resources[PMS_BAR],
.enable = cs5535_mfd_res_enable,
.disable = cs5535_mfd_res_disable,
},
{
.id = ACPI_BAR,
.name = "cs5535-acpi",
.num_resources = 1,
.resources = &cs5535_mfd_resources[ACPI_BAR],
.enable = cs5535_mfd_res_enable,
.disable = cs5535_mfd_res_disable,
}, },
}; };
static const char *olpc_acpi_clones[] = { static struct mfd_cell cs5535_olpc_mfd_cells[] = {
"olpc-xo1-pm-acpi", {
"olpc-xo1-sci-acpi" .name = "olpc-xo1-pm-acpi",
.num_resources = 1,
.resources = &cs5535_mfd_resources[ACPI_BAR],
},
{
.name = "olpc-xo1-sci-acpi",
.num_resources = 1,
.resources = &cs5535_mfd_resources[ACPI_BAR],
},
}; };
static int cs5535_mfd_probe(struct pci_dev *pdev, static int cs5535_mfd_probe(struct pci_dev *pdev,
const struct pci_device_id *id) const struct pci_device_id *id)
{ {
int err, i; int err, bar;
err = pci_enable_device(pdev); err = pci_enable_device(pdev);
if (err) if (err)
return err; return err;
/* fill in IO range for each cell; subdrivers handle the region */ for (bar = 0; bar < NR_BARS; bar++) {
for (i = 0; i < ARRAY_SIZE(cs5535_mfd_cells); i++) {
int bar = cs5535_mfd_cells[i].id;
struct resource *r = &cs5535_mfd_resources[bar]; struct resource *r = &cs5535_mfd_resources[bar];
r->flags = IORESOURCE_IO; r->flags = IORESOURCE_IO;
r->start = pci_resource_start(pdev, bar); r->start = pci_resource_start(pdev, bar);
r->end = pci_resource_end(pdev, bar); r->end = pci_resource_end(pdev, bar);
/* id is used for temporarily storing BAR; unset it now */
cs5535_mfd_cells[i].id = 0;
} }
err = mfd_add_devices(&pdev->dev, -1, cs5535_mfd_cells, err = pci_request_region(pdev, PMS_BAR, DRV_NAME);
ARRAY_SIZE(cs5535_mfd_cells), NULL, 0, NULL);
if (err) { if (err) {
dev_err(&pdev->dev, "MFD add devices failed: %d\n", err); dev_err(&pdev->dev, "Failed to request PMS_BAR's IO region\n");
goto err_disable; goto err_disable;
} }
if (machine_is_olpc()) err = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, cs5535_mfd_cells,
mfd_clone_cell("cs5535-acpi", olpc_acpi_clones, ARRAY_SIZE(olpc_acpi_clones)); ARRAY_SIZE(cs5535_mfd_cells), NULL, 0, NULL);
if (err) {
dev_err(&pdev->dev,
"Failed to add CS5535 sub-devices: %d\n", err);
goto err_release_pms;
}
if (machine_is_olpc()) {
err = pci_request_region(pdev, ACPI_BAR, DRV_NAME);
if (err) {
dev_err(&pdev->dev,
"Failed to request ACPI_BAR's IO region\n");
goto err_remove_devices;
}
err = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
cs5535_olpc_mfd_cells,
ARRAY_SIZE(cs5535_olpc_mfd_cells),
NULL, 0, NULL);
if (err) {
dev_err(&pdev->dev,
"Failed to add CS5535 OLPC sub-devices: %d\n",
err);
goto err_release_acpi;
}
}
dev_info(&pdev->dev, "%zu devices registered.\n", dev_info(&pdev->dev, "%zu devices registered.\n",
ARRAY_SIZE(cs5535_mfd_cells)); ARRAY_SIZE(cs5535_mfd_cells));
return 0; return 0;
err_release_acpi:
pci_release_region(pdev, ACPI_BAR);
err_remove_devices:
mfd_remove_devices(&pdev->dev);
err_release_pms:
pci_release_region(pdev, PMS_BAR);
err_disable: err_disable:
pci_disable_device(pdev); pci_disable_device(pdev);
return err; return err;
@ -150,6 +135,11 @@ static int cs5535_mfd_probe(struct pci_dev *pdev,
static void cs5535_mfd_remove(struct pci_dev *pdev) static void cs5535_mfd_remove(struct pci_dev *pdev)
{ {
mfd_remove_devices(&pdev->dev); mfd_remove_devices(&pdev->dev);
if (machine_is_olpc())
pci_release_region(pdev, ACPI_BAR);
pci_release_region(pdev, PMS_BAR);
pci_disable_device(pdev); pci_disable_device(pdev);
} }

View File

@ -27,6 +27,7 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
@ -668,6 +669,14 @@ struct prcmu_fw_version *prcmu_get_fw_version(void)
return fw_info.valid ? &fw_info.version : NULL; return fw_info.valid ? &fw_info.version : NULL;
} }
static bool prcmu_is_ulppll_disabled(void)
{
struct prcmu_fw_version *ver;
ver = prcmu_get_fw_version();
return ver && ver->project == PRCMU_FW_PROJECT_U8420_SYSCLK;
}
bool prcmu_has_arm_maxopp(void) bool prcmu_has_arm_maxopp(void)
{ {
return (readb(tcdm_base + PRCM_AVS_VARM_MAX_OPP) & return (readb(tcdm_base + PRCM_AVS_VARM_MAX_OPP) &
@ -1308,10 +1317,23 @@ static int request_sysclk(bool enable)
static int request_timclk(bool enable) static int request_timclk(bool enable)
{ {
u32 val = (PRCM_TCR_DOZE_MODE | PRCM_TCR_TENSEL_MASK); u32 val;
/*
* On the U8420_CLKSEL firmware, the ULP (Ultra Low Power)
* PLL is disabled so we cannot use doze mode, this will
* stop the clock on this firmware.
*/
if (prcmu_is_ulppll_disabled())
val = 0;
else
val = (PRCM_TCR_DOZE_MODE | PRCM_TCR_TENSEL_MASK);
if (!enable) if (!enable)
val |= PRCM_TCR_STOP_TIMERS; val |= PRCM_TCR_STOP_TIMERS |
PRCM_TCR_DOZE_MODE |
PRCM_TCR_TENSEL_MASK;
writel(val, PRCM_TCR); writel(val, PRCM_TCR);
return 0; return 0;
@ -1615,7 +1637,8 @@ unsigned long prcmu_clock_rate(u8 clock)
if (clock < PRCMU_NUM_REG_CLOCKS) if (clock < PRCMU_NUM_REG_CLOCKS)
return clock_rate(clock); return clock_rate(clock);
else if (clock == PRCMU_TIMCLK) else if (clock == PRCMU_TIMCLK)
return ROOT_CLOCK_RATE / 16; return prcmu_is_ulppll_disabled() ?
32768 : ROOT_CLOCK_RATE / 16;
else if (clock == PRCMU_SYSCLK) else if (clock == PRCMU_SYSCLK)
return ROOT_CLOCK_RATE; return ROOT_CLOCK_RATE;
else if (clock == PRCMU_PLLSOC0) else if (clock == PRCMU_PLLSOC0)
@ -2646,6 +2669,8 @@ static char *fw_project_name(u32 project)
return "U8520 MBL"; return "U8520 MBL";
case PRCMU_FW_PROJECT_U8420: case PRCMU_FW_PROJECT_U8420:
return "U8420"; return "U8420";
case PRCMU_FW_PROJECT_U8420_SYSCLK:
return "U8420-sysclk";
case PRCMU_FW_PROJECT_U9540: case PRCMU_FW_PROJECT_U9540:
return "U9540"; return "U9540";
case PRCMU_FW_PROJECT_A9420: case PRCMU_FW_PROJECT_A9420:
@ -2693,27 +2718,18 @@ static int db8500_irq_init(struct device_node *np)
return 0; return 0;
} }
static void dbx500_fw_version_init(struct platform_device *pdev, static void dbx500_fw_version_init(struct device_node *np)
u32 version_offset)
{ {
struct resource *res;
void __iomem *tcpm_base; void __iomem *tcpm_base;
u32 version; u32 version;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, tcpm_base = of_iomap(np, 1);
"prcmu-tcpm");
if (!res) {
dev_err(&pdev->dev,
"Error: no prcmu tcpm memory region provided\n");
return;
}
tcpm_base = ioremap(res->start, resource_size(res));
if (!tcpm_base) { if (!tcpm_base) {
dev_err(&pdev->dev, "no prcmu tcpm mem region provided\n"); pr_err("no prcmu tcpm mem region provided\n");
return; return;
} }
version = readl(tcpm_base + version_offset); version = readl(tcpm_base + DB8500_PRCMU_FW_VERSION_OFFSET);
fw_info.version.project = (version & 0xFF); fw_info.version.project = (version & 0xFF);
fw_info.version.api_version = (version >> 8) & 0xFF; fw_info.version.api_version = (version >> 8) & 0xFF;
fw_info.version.func_version = (version >> 16) & 0xFF; fw_info.version.func_version = (version >> 16) & 0xFF;
@ -2731,7 +2747,7 @@ static void dbx500_fw_version_init(struct platform_device *pdev,
iounmap(tcpm_base); iounmap(tcpm_base);
} }
void __init db8500_prcmu_early_init(u32 phy_base, u32 size) void __init db8500_prcmu_early_init(void)
{ {
/* /*
* This is a temporary remap to bring up the clocks. It is * This is a temporary remap to bring up the clocks. It is
@ -2740,9 +2756,17 @@ void __init db8500_prcmu_early_init(u32 phy_base, u32 size)
* clock driver can probe independently. An early initcall will * clock driver can probe independently. An early initcall will
* still be needed, but it can be diverted into drivers/clk/ux500. * still be needed, but it can be diverted into drivers/clk/ux500.
*/ */
prcmu_base = ioremap(phy_base, size); struct device_node *np;
if (!prcmu_base)
np = of_find_compatible_node(NULL, NULL, "stericsson,db8500-prcmu");
prcmu_base = of_iomap(np, 0);
if (!prcmu_base) {
of_node_put(np);
pr_err("%s: ioremap() of prcmu registers failed!\n", __func__); pr_err("%s: ioremap() of prcmu registers failed!\n", __func__);
return;
}
dbx500_fw_version_init(np);
of_node_put(np);
spin_lock_init(&mb0_transfer.lock); spin_lock_init(&mb0_transfer.lock);
spin_lock_init(&mb0_transfer.dbb_irqs_lock); spin_lock_init(&mb0_transfer.dbb_irqs_lock);
@ -3024,20 +3048,13 @@ static const struct mfd_cell common_prcmu_devs[] = {
}; };
static const struct mfd_cell db8500_prcmu_devs[] = { static const struct mfd_cell db8500_prcmu_devs[] = {
{ OF_MFD_CELL("db8500-prcmu-regulators", NULL,
.name = "db8500-prcmu-regulators", &db8500_regulators, sizeof(db8500_regulators), 0,
.of_compatible = "stericsson,db8500-prcmu-regulator", "stericsson,db8500-prcmu-regulator"),
.platform_data = &db8500_regulators, OF_MFD_CELL("cpuidle-dbx500",
.pdata_size = sizeof(db8500_regulators), NULL, NULL, 0, 0, "stericsson,cpuidle-dbx500"),
}, OF_MFD_CELL("db8500-thermal",
{ NULL, NULL, 0, 0, "stericsson,db8500-thermal"),
.name = "cpuidle-dbx500",
.of_compatible = "stericsson,cpuidle-dbx500",
},
{
.name = "db8500-thermal",
.of_compatible = "stericsson,db8500-thermal",
},
}; };
static int db8500_prcmu_register_ab8500(struct device *parent) static int db8500_prcmu_register_ab8500(struct device *parent)
@ -3091,7 +3108,6 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
} }
init_prcm_registers(); init_prcm_registers();
dbx500_fw_version_init(pdev, DB8500_PRCMU_FW_VERSION_OFFSET);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu-tcdm"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu-tcdm");
if (!res) { if (!res) {
dev_err(&pdev->dev, "no prcmu tcdm region provided\n"); dev_err(&pdev->dev, "no prcmu tcdm region provided\n");

View File

@ -122,13 +122,25 @@ static const struct intel_lpss_platform_info apl_i2c_info = {
.properties = apl_i2c_properties, .properties = apl_i2c_properties,
}; };
static struct property_entry glk_i2c_properties[] = {
PROPERTY_ENTRY_U32("i2c-sda-hold-time-ns", 313),
PROPERTY_ENTRY_U32("i2c-sda-falling-time-ns", 171),
PROPERTY_ENTRY_U32("i2c-scl-falling-time-ns", 290),
{ },
};
static const struct intel_lpss_platform_info glk_i2c_info = {
.clk_rate = 133000000,
.properties = glk_i2c_properties,
};
static const struct intel_lpss_platform_info cnl_i2c_info = { static const struct intel_lpss_platform_info cnl_i2c_info = {
.clk_rate = 216000000, .clk_rate = 216000000,
.properties = spt_i2c_properties, .properties = spt_i2c_properties,
}; };
static const struct pci_device_id intel_lpss_pci_ids[] = { static const struct pci_device_id intel_lpss_pci_ids[] = {
/* CML */ /* CML-LP */
{ PCI_VDEVICE(INTEL, 0x02a8), (kernel_ulong_t)&spt_uart_info }, { PCI_VDEVICE(INTEL, 0x02a8), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x02a9), (kernel_ulong_t)&spt_uart_info }, { PCI_VDEVICE(INTEL, 0x02a9), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x02aa), (kernel_ulong_t)&spt_info }, { PCI_VDEVICE(INTEL, 0x02aa), (kernel_ulong_t)&spt_info },
@ -141,6 +153,17 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x02ea), (kernel_ulong_t)&cnl_i2c_info }, { PCI_VDEVICE(INTEL, 0x02ea), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x02eb), (kernel_ulong_t)&cnl_i2c_info }, { PCI_VDEVICE(INTEL, 0x02eb), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x02fb), (kernel_ulong_t)&spt_info }, { PCI_VDEVICE(INTEL, 0x02fb), (kernel_ulong_t)&spt_info },
/* CML-H */
{ PCI_VDEVICE(INTEL, 0x06a8), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x06a9), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x06aa), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0x06ab), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0x06c7), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x06e8), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x06e9), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x06ea), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x06eb), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x06fb), (kernel_ulong_t)&spt_info },
/* BXT A-Step */ /* BXT A-Step */
{ PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x0aae), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x0aae), (kernel_ulong_t)&bxt_i2c_info },
@ -174,14 +197,14 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x1ac6), (kernel_ulong_t)&bxt_info }, { PCI_VDEVICE(INTEL, 0x1ac6), (kernel_ulong_t)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x1aee), (kernel_ulong_t)&bxt_uart_info }, { PCI_VDEVICE(INTEL, 0x1aee), (kernel_ulong_t)&bxt_uart_info },
/* GLK */ /* GLK */
{ PCI_VDEVICE(INTEL, 0x31ac), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x31ac), (kernel_ulong_t)&glk_i2c_info },
{ PCI_VDEVICE(INTEL, 0x31ae), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x31ae), (kernel_ulong_t)&glk_i2c_info },
{ PCI_VDEVICE(INTEL, 0x31b0), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x31b0), (kernel_ulong_t)&glk_i2c_info },
{ PCI_VDEVICE(INTEL, 0x31b2), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x31b2), (kernel_ulong_t)&glk_i2c_info },
{ PCI_VDEVICE(INTEL, 0x31b4), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x31b4), (kernel_ulong_t)&glk_i2c_info },
{ PCI_VDEVICE(INTEL, 0x31b6), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x31b6), (kernel_ulong_t)&glk_i2c_info },
{ PCI_VDEVICE(INTEL, 0x31b8), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x31b8), (kernel_ulong_t)&glk_i2c_info },
{ PCI_VDEVICE(INTEL, 0x31ba), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x31ba), (kernel_ulong_t)&glk_i2c_info },
{ PCI_VDEVICE(INTEL, 0x31bc), (kernel_ulong_t)&bxt_uart_info }, { PCI_VDEVICE(INTEL, 0x31bc), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x31be), (kernel_ulong_t)&bxt_uart_info }, { PCI_VDEVICE(INTEL, 0x31be), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x31c0), (kernel_ulong_t)&bxt_uart_info }, { PCI_VDEVICE(INTEL, 0x31c0), (kernel_ulong_t)&bxt_uart_info },

View File

@ -384,7 +384,7 @@ int intel_lpss_probe(struct device *dev,
if (!lpss) if (!lpss)
return -ENOMEM; return -ENOMEM;
lpss->priv = devm_ioremap(dev, info->mem->start + LPSS_PRIV_OFFSET, lpss->priv = devm_ioremap_uc(dev, info->mem->start + LPSS_PRIV_OFFSET,
LPSS_PRIV_SIZE); LPSS_PRIV_SIZE);
if (!lpss->priv) if (!lpss->priv)
return -ENOMEM; return -ENOMEM;

View File

@ -88,6 +88,9 @@ static struct mfd_cell crystal_cove_cht_dev[] = {
.num_resources = ARRAY_SIZE(gpio_resources), .num_resources = ARRAY_SIZE(gpio_resources),
.resources = gpio_resources, .resources = gpio_resources,
}, },
{
.name = "cht_crystal_cove_pmic",
},
{ {
.name = "crystal_cove_pwm", .name = "crystal_cove_pwm",
}, },

View File

@ -396,11 +396,7 @@ static int __init micro_probe(struct platform_device *pdev)
if (IS_ERR(micro->base)) if (IS_ERR(micro->base))
return PTR_ERR(micro->base); return PTR_ERR(micro->base);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1); micro->sdlc = devm_platform_ioremap_resource(pdev, 1);
if (!res)
return -EINVAL;
micro->sdlc = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(micro->sdlc)) if (IS_ERR(micro->sdlc))
return PTR_ERR(micro->sdlc); return PTR_ERR(micro->sdlc);

View File

@ -450,6 +450,21 @@ int madera_dev_init(struct madera *madera)
sizeof(madera->pdata)); sizeof(madera->pdata));
} }
madera->mclk[MADERA_MCLK1].id = "mclk1";
madera->mclk[MADERA_MCLK2].id = "mclk2";
madera->mclk[MADERA_MCLK3].id = "mclk3";
ret = devm_clk_bulk_get_optional(madera->dev, ARRAY_SIZE(madera->mclk),
madera->mclk);
if (ret) {
dev_err(madera->dev, "Failed to get clocks: %d\n", ret);
return ret;
}
/* Not using devm_clk_get to prevent breakage of existing DTs */
if (!madera->mclk[MADERA_MCLK2].clk)
dev_warn(madera->dev, "Missing MCLK2, requires 32kHz clock\n");
ret = madera_get_reset_gpio(madera); ret = madera_get_reset_gpio(madera);
if (ret) if (ret)
return ret; return ret;
@ -660,13 +675,19 @@ int madera_dev_init(struct madera *madera)
} }
/* Init 32k clock sourced from MCLK2 */ /* Init 32k clock sourced from MCLK2 */
ret = clk_prepare_enable(madera->mclk[MADERA_MCLK2].clk);
if (ret) {
dev_err(madera->dev, "Failed to enable 32k clock: %d\n", ret);
goto err_reset;
}
ret = regmap_update_bits(madera->regmap, ret = regmap_update_bits(madera->regmap,
MADERA_CLOCK_32K_1, MADERA_CLOCK_32K_1,
MADERA_CLK_32K_ENA_MASK | MADERA_CLK_32K_SRC_MASK, MADERA_CLK_32K_ENA_MASK | MADERA_CLK_32K_SRC_MASK,
MADERA_CLK_32K_ENA | MADERA_32KZ_MCLK2); MADERA_CLK_32K_ENA | MADERA_32KZ_MCLK2);
if (ret) { if (ret) {
dev_err(madera->dev, "Failed to init 32k clock: %d\n", ret); dev_err(madera->dev, "Failed to init 32k clock: %d\n", ret);
goto err_reset; goto err_clock;
} }
pm_runtime_set_active(madera->dev); pm_runtime_set_active(madera->dev);
@ -687,6 +708,8 @@ int madera_dev_init(struct madera *madera)
err_pm_runtime: err_pm_runtime:
pm_runtime_disable(madera->dev); pm_runtime_disable(madera->dev);
err_clock:
clk_disable_unprepare(madera->mclk[MADERA_MCLK2].clk);
err_reset: err_reset:
madera_enable_hard_reset(madera); madera_enable_hard_reset(madera);
regulator_disable(madera->dcvdd); regulator_disable(madera->dcvdd);
@ -713,6 +736,8 @@ int madera_dev_exit(struct madera *madera)
*/ */
pm_runtime_disable(madera->dev); pm_runtime_disable(madera->dev);
clk_disable_unprepare(madera->mclk[MADERA_MCLK2].clk);
regulator_disable(madera->dcvdd); regulator_disable(madera->dcvdd);
regulator_put(madera->dcvdd); regulator_put(madera->dcvdd);

View File

@ -507,7 +507,6 @@ static int max77620_probe(struct i2c_client *client,
i2c_set_clientdata(client, chip); i2c_set_clientdata(client, chip);
chip->dev = &client->dev; chip->dev = &client->dev;
chip->irq_base = -1;
chip->chip_irq = client->irq; chip->chip_irq = client->irq;
chip->chip_id = (enum max77620_chip_id)id->driver_data; chip->chip_id = (enum max77620_chip_id)id->driver_data;
@ -545,8 +544,8 @@ static int max77620_probe(struct i2c_client *client,
max77620_top_irq_chip.irq_drv_data = chip; max77620_top_irq_chip.irq_drv_data = chip;
ret = devm_regmap_add_irq_chip(chip->dev, chip->rmap, client->irq, ret = devm_regmap_add_irq_chip(chip->dev, chip->rmap, client->irq,
IRQF_ONESHOT | IRQF_SHARED, IRQF_ONESHOT | IRQF_SHARED, 0,
chip->irq_base, &max77620_top_irq_chip, &max77620_top_irq_chip,
&chip->top_irq_data); &chip->top_irq_data);
if (ret < 0) { if (ret < 0) {
dev_err(chip->dev, "Failed to add regmap irq: %d\n", ret); dev_err(chip->dev, "Failed to add regmap irq: %d\n", ret);

View File

@ -26,55 +26,29 @@ static struct device_type mfd_dev_type = {
int mfd_cell_enable(struct platform_device *pdev) int mfd_cell_enable(struct platform_device *pdev)
{ {
const struct mfd_cell *cell = mfd_get_cell(pdev); const struct mfd_cell *cell = mfd_get_cell(pdev);
int err = 0;
/* only call enable hook if the cell wasn't previously enabled */ if (!cell->enable) {
if (atomic_inc_return(cell->usage_count) == 1) dev_dbg(&pdev->dev, "No .enable() call-back registered\n");
err = cell->enable(pdev); return 0;
}
/* if the enable hook failed, decrement counter to allow retries */ return cell->enable(pdev);
if (err)
atomic_dec(cell->usage_count);
return err;
} }
EXPORT_SYMBOL(mfd_cell_enable); EXPORT_SYMBOL(mfd_cell_enable);
int mfd_cell_disable(struct platform_device *pdev) int mfd_cell_disable(struct platform_device *pdev)
{ {
const struct mfd_cell *cell = mfd_get_cell(pdev); const struct mfd_cell *cell = mfd_get_cell(pdev);
int err = 0;
/* only disable if no other clients are using it */ if (!cell->disable) {
if (atomic_dec_return(cell->usage_count) == 0) dev_dbg(&pdev->dev, "No .disable() call-back registered\n");
err = cell->disable(pdev); return 0;
}
/* if the disable hook failed, increment to allow retries */ return cell->disable(pdev);
if (err)
atomic_inc(cell->usage_count);
/* sanity check; did someone call disable too many times? */
WARN_ON(atomic_read(cell->usage_count) < 0);
return err;
} }
EXPORT_SYMBOL(mfd_cell_disable); EXPORT_SYMBOL(mfd_cell_disable);
static int mfd_platform_add_cell(struct platform_device *pdev,
const struct mfd_cell *cell,
atomic_t *usage_count)
{
if (!cell)
return 0;
pdev->mfd_cell = kmemdup(cell, sizeof(*cell), GFP_KERNEL);
if (!pdev->mfd_cell)
return -ENOMEM;
pdev->mfd_cell->usage_count = usage_count;
return 0;
}
#if IS_ENABLED(CONFIG_ACPI) #if IS_ENABLED(CONFIG_ACPI)
static void mfd_acpi_add_device(const struct mfd_cell *cell, static void mfd_acpi_add_device(const struct mfd_cell *cell,
struct platform_device *pdev) struct platform_device *pdev)
@ -134,7 +108,7 @@ static inline void mfd_acpi_add_device(const struct mfd_cell *cell,
#endif #endif
static int mfd_add_device(struct device *parent, int id, static int mfd_add_device(struct device *parent, int id,
const struct mfd_cell *cell, atomic_t *usage_count, const struct mfd_cell *cell,
struct resource *mem_base, struct resource *mem_base,
int irq_base, struct irq_domain *domain) int irq_base, struct irq_domain *domain)
{ {
@ -154,6 +128,10 @@ static int mfd_add_device(struct device *parent, int id,
if (!pdev) if (!pdev)
goto fail_alloc; goto fail_alloc;
pdev->mfd_cell = kmemdup(cell, sizeof(*cell), GFP_KERNEL);
if (!pdev->mfd_cell)
goto fail_device;
res = kcalloc(cell->num_resources, sizeof(*res), GFP_KERNEL); res = kcalloc(cell->num_resources, sizeof(*res), GFP_KERNEL);
if (!res) if (!res)
goto fail_device; goto fail_device;
@ -174,6 +152,11 @@ static int mfd_add_device(struct device *parent, int id,
if (parent->of_node && cell->of_compatible) { if (parent->of_node && cell->of_compatible) {
for_each_child_of_node(parent->of_node, np) { for_each_child_of_node(parent->of_node, np) {
if (of_device_is_compatible(np, cell->of_compatible)) { if (of_device_is_compatible(np, cell->of_compatible)) {
if (!of_device_is_available(np)) {
/* Ignore disabled devices error free */
ret = 0;
goto fail_alias;
}
pdev->dev.of_node = np; pdev->dev.of_node = np;
pdev->dev.fwnode = &np->fwnode; pdev->dev.fwnode = &np->fwnode;
break; break;
@ -196,10 +179,6 @@ static int mfd_add_device(struct device *parent, int id,
goto fail_alias; goto fail_alias;
} }
ret = mfd_platform_add_cell(pdev, cell, usage_count);
if (ret)
goto fail_alias;
for (r = 0; r < cell->num_resources; r++) { for (r = 0; r < cell->num_resources; r++) {
res[r].name = cell->resources[r].name; res[r].name = cell->resources[r].name;
res[r].flags = cell->resources[r].flags; res[r].flags = cell->resources[r].flags;
@ -286,16 +265,9 @@ int mfd_add_devices(struct device *parent, int id,
{ {
int i; int i;
int ret; int ret;
atomic_t *cnts;
/* initialize reference counting for all cells */
cnts = kcalloc(n_devs, sizeof(*cnts), GFP_KERNEL);
if (!cnts)
return -ENOMEM;
for (i = 0; i < n_devs; i++) { for (i = 0; i < n_devs; i++) {
atomic_set(&cnts[i], 0); ret = mfd_add_device(parent, id, cells + i, mem_base,
ret = mfd_add_device(parent, id, cells + i, cnts + i, mem_base,
irq_base, domain); irq_base, domain);
if (ret) if (ret)
goto fail; goto fail;
@ -306,17 +278,15 @@ int mfd_add_devices(struct device *parent, int id,
fail: fail:
if (i) if (i)
mfd_remove_devices(parent); mfd_remove_devices(parent);
else
kfree(cnts);
return ret; return ret;
} }
EXPORT_SYMBOL(mfd_add_devices); EXPORT_SYMBOL(mfd_add_devices);
static int mfd_remove_devices_fn(struct device *dev, void *c) static int mfd_remove_devices_fn(struct device *dev, void *data)
{ {
struct platform_device *pdev; struct platform_device *pdev;
const struct mfd_cell *cell; const struct mfd_cell *cell;
atomic_t **usage_count = c;
if (dev->type != &mfd_dev_type) if (dev->type != &mfd_dev_type)
return 0; return 0;
@ -327,20 +297,13 @@ static int mfd_remove_devices_fn(struct device *dev, void *c)
regulator_bulk_unregister_supply_alias(dev, cell->parent_supplies, regulator_bulk_unregister_supply_alias(dev, cell->parent_supplies,
cell->num_parent_supplies); cell->num_parent_supplies);
/* find the base address of usage_count pointers (for freeing) */
if (!*usage_count || (cell->usage_count < *usage_count))
*usage_count = cell->usage_count;
platform_device_unregister(pdev); platform_device_unregister(pdev);
return 0; return 0;
} }
void mfd_remove_devices(struct device *parent) void mfd_remove_devices(struct device *parent)
{ {
atomic_t *cnts = NULL; device_for_each_child_reverse(parent, NULL, mfd_remove_devices_fn);
device_for_each_child_reverse(parent, &cnts, mfd_remove_devices_fn);
kfree(cnts);
} }
EXPORT_SYMBOL(mfd_remove_devices); EXPORT_SYMBOL(mfd_remove_devices);
@ -382,38 +345,5 @@ int devm_mfd_add_devices(struct device *dev, int id,
} }
EXPORT_SYMBOL(devm_mfd_add_devices); EXPORT_SYMBOL(devm_mfd_add_devices);
int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones)
{
struct mfd_cell cell_entry;
struct device *dev;
struct platform_device *pdev;
int i;
/* fetch the parent cell's device (should already be registered!) */
dev = bus_find_device_by_name(&platform_bus_type, NULL, cell);
if (!dev) {
printk(KERN_ERR "failed to find device for cell %s\n", cell);
return -ENODEV;
}
pdev = to_platform_device(dev);
memcpy(&cell_entry, mfd_get_cell(pdev), sizeof(cell_entry));
WARN_ON(!cell_entry.enable);
for (i = 0; i < n_clones; i++) {
cell_entry.name = clones[i];
/* don't give up if a single call fails; just report error */
if (mfd_add_device(pdev->dev.parent, -1, &cell_entry,
cell_entry.usage_count, NULL, 0, NULL))
dev_err(dev, "failed to create platform device '%s'\n",
clones[i]);
}
put_device(dev);
return 0;
}
EXPORT_SYMBOL(mfd_clone_cell);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov"); MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov");

View File

@ -189,16 +189,16 @@ static int mt6397_probe(struct platform_device *pdev)
switch (pmic->chip_id) { switch (pmic->chip_id) {
case MT6323_CHIP_ID: case MT6323_CHIP_ID:
ret = devm_mfd_add_devices(&pdev->dev, -1, mt6323_devs, ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
ARRAY_SIZE(mt6323_devs), NULL, mt6323_devs, ARRAY_SIZE(mt6323_devs),
0, pmic->irq_domain); NULL, 0, pmic->irq_domain);
break; break;
case MT6391_CHIP_ID: case MT6391_CHIP_ID:
case MT6397_CHIP_ID: case MT6397_CHIP_ID:
ret = devm_mfd_add_devices(&pdev->dev, -1, mt6397_devs, ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
ARRAY_SIZE(mt6397_devs), NULL, mt6397_devs, ARRAY_SIZE(mt6397_devs),
0, pmic->irq_domain); NULL, 0, pmic->irq_domain);
break; break;
default: default:

View File

@ -31,6 +31,8 @@
#define PM8916_SUBTYPE 0x0b #define PM8916_SUBTYPE 0x0b
#define PM8004_SUBTYPE 0x0c #define PM8004_SUBTYPE 0x0c
#define PM8909_SUBTYPE 0x0d #define PM8909_SUBTYPE 0x0d
#define PM8950_SUBTYPE 0x10
#define PMI8950_SUBTYPE 0x11
#define PM8998_SUBTYPE 0x14 #define PM8998_SUBTYPE 0x14
#define PMI8998_SUBTYPE 0x15 #define PMI8998_SUBTYPE 0x15
#define PM8005_SUBTYPE 0x18 #define PM8005_SUBTYPE 0x18
@ -50,6 +52,8 @@ static const struct of_device_id pmic_spmi_id_table[] = {
{ .compatible = "qcom,pm8916", .data = (void *)PM8916_SUBTYPE }, { .compatible = "qcom,pm8916", .data = (void *)PM8916_SUBTYPE },
{ .compatible = "qcom,pm8004", .data = (void *)PM8004_SUBTYPE }, { .compatible = "qcom,pm8004", .data = (void *)PM8004_SUBTYPE },
{ .compatible = "qcom,pm8909", .data = (void *)PM8909_SUBTYPE }, { .compatible = "qcom,pm8909", .data = (void *)PM8909_SUBTYPE },
{ .compatible = "qcom,pm8950", .data = (void *)PM8950_SUBTYPE },
{ .compatible = "qcom,pmi8950", .data = (void *)PMI8950_SUBTYPE },
{ .compatible = "qcom,pm8998", .data = (void *)PM8998_SUBTYPE }, { .compatible = "qcom,pm8998", .data = (void *)PM8998_SUBTYPE },
{ .compatible = "qcom,pmi8998", .data = (void *)PMI8998_SUBTYPE }, { .compatible = "qcom,pmi8998", .data = (void *)PMI8998_SUBTYPE },
{ .compatible = "qcom,pm8005", .data = (void *)PM8005_SUBTYPE }, { .compatible = "qcom,pm8005", .data = (void *)PM8005_SUBTYPE },

View File

@ -109,11 +109,7 @@ static const struct regmap_config rk817_regmap_config = {
}; };
static struct resource rtc_resources[] = { static struct resource rtc_resources[] = {
{ DEFINE_RES_IRQ(RK808_IRQ_RTC_ALARM),
.start = RK808_IRQ_RTC_ALARM,
.end = RK808_IRQ_RTC_ALARM,
.flags = IORESOURCE_IRQ,
}
}; };
static struct resource rk817_rtc_resources[] = { static struct resource rk817_rtc_resources[] = {
@ -121,16 +117,8 @@ static struct resource rk817_rtc_resources[] = {
}; };
static struct resource rk805_key_resources[] = { static struct resource rk805_key_resources[] = {
{ DEFINE_RES_IRQ(RK805_IRQ_PWRON_RISE),
.start = RK805_IRQ_PWRON_FALL, DEFINE_RES_IRQ(RK805_IRQ_PWRON_FALL),
.end = RK805_IRQ_PWRON_FALL,
.flags = IORESOURCE_IRQ,
},
{
.start = RK805_IRQ_PWRON_RISE,
.end = RK805_IRQ_PWRON_RISE,
.flags = IORESOURCE_IRQ,
}
}; };
static struct resource rk817_pwrkey_resources[] = { static struct resource rk817_pwrkey_resources[] = {
@ -167,7 +155,7 @@ static const struct mfd_cell rk817s[] = {
{ .name = "rk808-clkout",}, { .name = "rk808-clkout",},
{ .name = "rk808-regulator",}, { .name = "rk808-regulator",},
{ {
.name = "rk8xx-pwrkey", .name = "rk805-pwrkey",
.num_resources = ARRAY_SIZE(rk817_pwrkey_resources), .num_resources = ARRAY_SIZE(rk817_pwrkey_resources),
.resources = &rk817_pwrkey_resources[0], .resources = &rk817_pwrkey_resources[0],
}, },
@ -215,7 +203,7 @@ static const struct rk808_reg_data rk808_pre_init_reg[] = {
static const struct rk808_reg_data rk817_pre_init_reg[] = { static const struct rk808_reg_data rk817_pre_init_reg[] = {
{RK817_RTC_CTRL_REG, RTC_STOP, RTC_STOP}, {RK817_RTC_CTRL_REG, RTC_STOP, RTC_STOP},
{RK817_GPIO_INT_CFG, RK817_INT_POL_MSK, RK817_INT_POL_H}, {RK817_GPIO_INT_CFG, RK817_INT_POL_MSK, RK817_INT_POL_L},
{RK817_SYS_CFG(1), RK817_HOTDIE_TEMP_MSK | RK817_TSD_TEMP_MSK, {RK817_SYS_CFG(1), RK817_HOTDIE_TEMP_MSK | RK817_TSD_TEMP_MSK,
RK817_HOTDIE_105 | RK817_TSD_140}, RK817_HOTDIE_105 | RK817_TSD_140},
}; };

View File

@ -105,15 +105,14 @@ static struct regmap_config bd70528_regmap = {
* register. * register.
*/ */
/* bit [0] - Shutdown register */ static unsigned int bit0_offsets[] = {0}; /* Shutdown */
unsigned int bit0_offsets[] = {0}; /* Shutdown register */ static unsigned int bit1_offsets[] = {1}; /* Power failure */
unsigned int bit1_offsets[] = {1}; /* Power failure register */ static unsigned int bit2_offsets[] = {2}; /* VR FAULT */
unsigned int bit2_offsets[] = {2}; /* VR FAULT register */ static unsigned int bit3_offsets[] = {3}; /* PMU interrupts */
unsigned int bit3_offsets[] = {3}; /* PMU register interrupts */ static unsigned int bit4_offsets[] = {4, 5}; /* Charger 1 and Charger 2 */
unsigned int bit4_offsets[] = {4, 5}; /* Charger 1 and Charger 2 registers */ static unsigned int bit5_offsets[] = {6}; /* RTC */
unsigned int bit5_offsets[] = {6}; /* RTC register */ static unsigned int bit6_offsets[] = {7}; /* GPIO */
unsigned int bit6_offsets[] = {7}; /* GPIO register */ static unsigned int bit7_offsets[] = {8}; /* Invalid operation */
unsigned int bit7_offsets[] = {8}; /* Invalid operation register */
static struct regmap_irq_sub_irq_map bd70528_sub_irq_offsets[] = { static struct regmap_irq_sub_irq_map bd70528_sub_irq_offsets[] = {
REGMAP_IRQ_MAIN_REG_OFFSET(bit0_offsets), REGMAP_IRQ_MAIN_REG_OFFSET(bit0_offsets),

View File

@ -105,7 +105,6 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_clk)
syscon_config.reg_stride = reg_io_width; syscon_config.reg_stride = reg_io_width;
syscon_config.val_bits = reg_io_width * 8; syscon_config.val_bits = reg_io_width * 8;
syscon_config.max_register = resource_size(&res) - reg_io_width; syscon_config.max_register = resource_size(&res) - reg_io_width;
syscon_config.name = of_node_full_name(np);
regmap = regmap_init_mmio(NULL, base, &syscon_config); regmap = regmap_init_mmio(NULL, base, &syscon_config);
if (IS_ERR(regmap)) { if (IS_ERR(regmap)) {

View File

@ -182,11 +182,11 @@ static int ti_tscadc_probe(struct platform_device *pdev)
tscadc->irq = err; tscadc->irq = err;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
tscadc->tscadc_phys_base = res->start;
tscadc->tscadc_base = devm_ioremap_resource(&pdev->dev, res); tscadc->tscadc_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(tscadc->tscadc_base)) if (IS_ERR(tscadc->tscadc_base))
return PTR_ERR(tscadc->tscadc_base); return PTR_ERR(tscadc->tscadc_base);
tscadc->tscadc_phys_base = res->start;
tscadc->regmap = devm_regmap_init_mmio(&pdev->dev, tscadc->regmap = devm_regmap_init_mmio(&pdev->dev,
tscadc->tscadc_base, &tscadc_regmap_config); tscadc->tscadc_base, &tscadc_regmap_config);
if (IS_ERR(tscadc->regmap)) { if (IS_ERR(tscadc->regmap)) {

View File

@ -806,12 +806,6 @@ static const struct reg_default wm8998_reg_default[] = {
{ 0x00000EF3, 0x0000 }, /* R3827 - ISRC 2 CTRL 1 */ { 0x00000EF3, 0x0000 }, /* R3827 - ISRC 2 CTRL 1 */
{ 0x00000EF4, 0x0001 }, /* R3828 - ISRC 2 CTRL 2 */ { 0x00000EF4, 0x0001 }, /* R3828 - ISRC 2 CTRL 2 */
{ 0x00000EF5, 0x0000 }, /* R3829 - ISRC 2 CTRL 3 */ { 0x00000EF5, 0x0000 }, /* R3829 - ISRC 2 CTRL 3 */
{ 0x00001700, 0x0000 }, /* R5888 - FRF_COEFF_1 */
{ 0x00001701, 0x0000 }, /* R5889 - FRF_COEFF_2 */
{ 0x00001702, 0x0000 }, /* R5890 - FRF_COEFF_3 */
{ 0x00001703, 0x0000 }, /* R5891 - FRF_COEFF_4 */
{ 0x00001704, 0x0000 }, /* R5892 - DAC_COMP_1 */
{ 0x00001705, 0x0000 }, /* R5893 - DAC_COMP_2 */
}; };
static bool wm8998_readable_register(struct device *dev, unsigned int reg) static bool wm8998_readable_register(struct device *dev, unsigned int reg)
@ -1492,12 +1486,6 @@ static bool wm8998_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_ISRC_2_CTRL_1: case ARIZONA_ISRC_2_CTRL_1:
case ARIZONA_ISRC_2_CTRL_2: case ARIZONA_ISRC_2_CTRL_2:
case ARIZONA_ISRC_2_CTRL_3: case ARIZONA_ISRC_2_CTRL_3:
case ARIZONA_FRF_COEFF_1:
case ARIZONA_FRF_COEFF_2:
case ARIZONA_FRF_COEFF_3:
case ARIZONA_FRF_COEFF_4:
case ARIZONA_V2_DAC_COMP_1:
case ARIZONA_V2_DAC_COMP_2:
return true; return true;
default: default:
return false; return false;

View File

@ -140,6 +140,16 @@ config POWER_RESET_LTC2952
This driver supports an external powerdown trigger and board power This driver supports an external powerdown trigger and board power
down via the LTC2952. Bindings are made in the device tree. down via the LTC2952. Bindings are made in the device tree.
config POWER_RESET_MT6323
bool "MediaTek MT6323 power-off driver"
depends on MFD_MT6397
help
The power-off driver is responsible for externally shutdown down
the power of a remote MediaTek SoC MT6323 is connected to through
controlling a tiny circuit BBPU inside MT6323 RTC.
Say Y if you have a board where MT6323 could be found.
config POWER_RESET_QNAP config POWER_RESET_QNAP
bool "QNAP power-off driver" bool "QNAP power-off driver"
depends on OF_GPIO && PLAT_ORION depends on OF_GPIO && PLAT_ORION

View File

@ -11,6 +11,7 @@ obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o
obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
obj-$(CONFIG_POWER_RESET_MT6323) += mt6323-poweroff.o
obj-$(CONFIG_POWER_RESET_QCOM_PON) += qcom-pon.o obj-$(CONFIG_POWER_RESET_QCOM_PON) += qcom-pon.o
obj-$(CONFIG_POWER_RESET_OCELOT_RESET) += ocelot-reset.o obj-$(CONFIG_POWER_RESET_OCELOT_RESET) += ocelot-reset.o
obj-$(CONFIG_POWER_RESET_PIIX4_POWEROFF) += piix4-poweroff.o obj-$(CONFIG_POWER_RESET_PIIX4_POWEROFF) += piix4-poweroff.o

View File

@ -0,0 +1,97 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Power off through MediaTek PMIC
*
* Copyright (C) 2018 MediaTek Inc.
*
* Author: Sean Wang <sean.wang@mediatek.com>
*
*/
#include <linux/err.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6397/rtc.h>
struct mt6323_pwrc {
struct device *dev;
struct regmap *regmap;
u32 base;
};
static struct mt6323_pwrc *mt_pwrc;
static void mt6323_do_pwroff(void)
{
struct mt6323_pwrc *pwrc = mt_pwrc;
unsigned int val;
int ret;
regmap_write(pwrc->regmap, pwrc->base + RTC_BBPU, RTC_BBPU_KEY);
regmap_write(pwrc->regmap, pwrc->base + RTC_WRTGR, 1);
ret = regmap_read_poll_timeout(pwrc->regmap,
pwrc->base + RTC_BBPU, val,
!(val & RTC_BBPU_CBUSY),
MTK_RTC_POLL_DELAY_US,
MTK_RTC_POLL_TIMEOUT);
if (ret)
dev_err(pwrc->dev, "failed to write BBPU: %d\n", ret);
/* Wait some time until system down, otherwise, notice with a warn */
mdelay(1000);
WARN_ONCE(1, "Unable to power off system\n");
}
static int mt6323_pwrc_probe(struct platform_device *pdev)
{
struct mt6397_chip *mt6397_chip = dev_get_drvdata(pdev->dev.parent);
struct mt6323_pwrc *pwrc;
struct resource *res;
pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL);
if (!pwrc)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pwrc->base = res->start;
pwrc->regmap = mt6397_chip->regmap;
pwrc->dev = &pdev->dev;
mt_pwrc = pwrc;
pm_power_off = &mt6323_do_pwroff;
return 0;
}
static int mt6323_pwrc_remove(struct platform_device *pdev)
{
if (pm_power_off == &mt6323_do_pwroff)
pm_power_off = NULL;
return 0;
}
static const struct of_device_id mt6323_pwrc_dt_match[] = {
{ .compatible = "mediatek,mt6323-pwrc" },
{},
};
MODULE_DEVICE_TABLE(of, mt6323_pwrc_dt_match);
static struct platform_driver mt6323_pwrc_driver = {
.probe = mt6323_pwrc_probe,
.remove = mt6323_pwrc_remove,
.driver = {
.name = "mt6323-pwrc",
.of_match_table = mt6323_pwrc_dt_match,
},
};
module_platform_driver(mt6323_pwrc_driver);
MODULE_DESCRIPTION("Poweroff driver for MT6323 PMIC");
MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
MODULE_LICENSE("GPL v2");

View File

@ -4,69 +4,19 @@
* Author: Tianping.Fang <tianping.fang@mediatek.com> * Author: Tianping.Fang <tianping.fang@mediatek.com>
*/ */
#include <linux/delay.h> #include <linux/err.h>
#include <linux/init.h> #include <linux/interrupt.h>
#include <linux/mfd/mt6397/core.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/irqdomain.h> #include <linux/mfd/mt6397/rtc.h>
#include <linux/platform_device.h> #include <linux/mod_devicetable.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/io.h>
#include <linux/mfd/mt6397/core.h>
#define RTC_BBPU 0x0000
#define RTC_BBPU_CBUSY BIT(6)
#define RTC_WRTGR 0x003c
#define RTC_IRQ_STA 0x0002
#define RTC_IRQ_STA_AL BIT(0)
#define RTC_IRQ_STA_LP BIT(3)
#define RTC_IRQ_EN 0x0004
#define RTC_IRQ_EN_AL BIT(0)
#define RTC_IRQ_EN_ONESHOT BIT(2)
#define RTC_IRQ_EN_LP BIT(3)
#define RTC_IRQ_EN_ONESHOT_AL (RTC_IRQ_EN_ONESHOT | RTC_IRQ_EN_AL)
#define RTC_AL_MASK 0x0008
#define RTC_AL_MASK_DOW BIT(4)
#define RTC_TC_SEC 0x000a
/* Min, Hour, Dom... register offset to RTC_TC_SEC */
#define RTC_OFFSET_SEC 0
#define RTC_OFFSET_MIN 1
#define RTC_OFFSET_HOUR 2
#define RTC_OFFSET_DOM 3
#define RTC_OFFSET_DOW 4
#define RTC_OFFSET_MTH 5
#define RTC_OFFSET_YEAR 6
#define RTC_OFFSET_COUNT 7
#define RTC_AL_SEC 0x0018
#define RTC_PDN2 0x002e
#define RTC_PDN2_PWRON_ALARM BIT(4)
#define RTC_MIN_YEAR 1968
#define RTC_BASE_YEAR 1900
#define RTC_NUM_YEARS 128
#define RTC_MIN_YEAR_OFFSET (RTC_MIN_YEAR - RTC_BASE_YEAR)
struct mt6397_rtc {
struct device *dev;
struct rtc_device *rtc_dev;
struct mutex lock;
struct regmap *regmap;
int irq;
u32 addr_base;
};
static int mtk_rtc_write_trigger(struct mt6397_rtc *rtc) static int mtk_rtc_write_trigger(struct mt6397_rtc *rtc)
{ {
unsigned long timeout = jiffies + HZ;
int ret; int ret;
u32 data; u32 data;
@ -74,19 +24,13 @@ static int mtk_rtc_write_trigger(struct mt6397_rtc *rtc)
if (ret < 0) if (ret < 0)
return ret; return ret;
while (1) { ret = regmap_read_poll_timeout(rtc->regmap,
ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_BBPU, rtc->addr_base + RTC_BBPU, data,
&data); !(data & RTC_BBPU_CBUSY),
MTK_RTC_POLL_DELAY_US,
MTK_RTC_POLL_TIMEOUT);
if (ret < 0) if (ret < 0)
break; dev_err(rtc->dev, "failed to write WRTGE: %d\n", ret);
if (!(data & RTC_BBPU_CBUSY))
break;
if (time_after(jiffies, timeout)) {
ret = -ETIMEDOUT;
break;
}
cpu_relax();
}
return ret; return ret;
} }
@ -319,19 +263,19 @@ static int mtk_rtc_probe(struct platform_device *pdev)
return rtc->irq; return rtc->irq;
rtc->regmap = mt6397_chip->regmap; rtc->regmap = mt6397_chip->regmap;
rtc->dev = &pdev->dev;
mutex_init(&rtc->lock); mutex_init(&rtc->lock);
platform_set_drvdata(pdev, rtc); platform_set_drvdata(pdev, rtc);
rtc->rtc_dev = devm_rtc_allocate_device(rtc->dev); rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc->rtc_dev)) if (IS_ERR(rtc->rtc_dev))
return PTR_ERR(rtc->rtc_dev); return PTR_ERR(rtc->rtc_dev);
ret = request_threaded_irq(rtc->irq, NULL, ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
mtk_rtc_irq_handler_thread, mtk_rtc_irq_handler_thread,
IRQF_ONESHOT | IRQF_TRIGGER_HIGH, IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
"mt6397-rtc", rtc); "mt6397-rtc", rtc);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
rtc->irq, ret); rtc->irq, ret);
@ -353,15 +297,6 @@ static int mtk_rtc_probe(struct platform_device *pdev)
return ret; return ret;
} }
static int mtk_rtc_remove(struct platform_device *pdev)
{
struct mt6397_rtc *rtc = platform_get_drvdata(pdev);
free_irq(rtc->irq, rtc);
return 0;
}
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int mt6397_rtc_suspend(struct device *dev) static int mt6397_rtc_suspend(struct device *dev)
{ {
@ -388,6 +323,7 @@ static SIMPLE_DEV_PM_OPS(mt6397_pm_ops, mt6397_rtc_suspend,
mt6397_rtc_resume); mt6397_rtc_resume);
static const struct of_device_id mt6397_rtc_of_match[] = { static const struct of_device_id mt6397_rtc_of_match[] = {
{ .compatible = "mediatek,mt6323-rtc", },
{ .compatible = "mediatek,mt6397-rtc", }, { .compatible = "mediatek,mt6397-rtc", },
{ } { }
}; };
@ -400,7 +336,6 @@ static struct platform_driver mtk_rtc_driver = {
.pm = &mt6397_pm_ops, .pm = &mt6397_pm_ops,
}, },
.probe = mtk_rtc_probe, .probe = mtk_rtc_probe,
.remove = mtk_rtc_remove,
}; };
module_platform_driver(mtk_rtc_driver); module_platform_driver(mtk_rtc_driver);

View File

@ -64,6 +64,8 @@ static inline void devm_ioport_unmap(struct device *dev, void __iomem *addr)
void __iomem *devm_ioremap(struct device *dev, resource_size_t offset, void __iomem *devm_ioremap(struct device *dev, resource_size_t offset,
resource_size_t size); resource_size_t size);
void __iomem *devm_ioremap_uc(struct device *dev, resource_size_t offset,
resource_size_t size);
void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset, void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset,
resource_size_t size); resource_size_t size);
void __iomem *devm_ioremap_wc(struct device *dev, resource_size_t offset, void __iomem *devm_ioremap_wc(struct device *dev, resource_size_t offset,

View File

@ -1186,13 +1186,6 @@
#define ARIZONA_DSP4_SCRATCH_1 0x1441 #define ARIZONA_DSP4_SCRATCH_1 0x1441
#define ARIZONA_DSP4_SCRATCH_2 0x1442 #define ARIZONA_DSP4_SCRATCH_2 0x1442
#define ARIZONA_DSP4_SCRATCH_3 0x1443 #define ARIZONA_DSP4_SCRATCH_3 0x1443
#define ARIZONA_FRF_COEFF_1 0x1700
#define ARIZONA_FRF_COEFF_2 0x1701
#define ARIZONA_FRF_COEFF_3 0x1702
#define ARIZONA_FRF_COEFF_4 0x1703
#define ARIZONA_V2_DAC_COMP_1 0x1704
#define ARIZONA_V2_DAC_COMP_2 0x1705
/* /*
* Field Definitions. * Field Definitions.

View File

@ -12,6 +12,35 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#define MFD_RES_SIZE(arr) (sizeof(arr) / sizeof(struct resource))
#define MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, _compat, _match)\
{ \
.name = (_name), \
.resources = (_res), \
.num_resources = MFD_RES_SIZE((_res)), \
.platform_data = (_pdata), \
.pdata_size = (_pdsize), \
.of_compatible = (_compat), \
.acpi_match = (_match), \
.id = (_id), \
}
#define OF_MFD_CELL(_name, _res, _pdata, _pdsize,_id, _compat) \
MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, _compat, NULL) \
#define ACPI_MFD_CELL(_name, _res, _pdata, _pdsize, _id, _match) \
MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, NULL, _match) \
#define MFD_CELL_BASIC(_name, _res, _pdata, _pdsize, _id) \
MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, NULL, NULL) \
#define MFD_CELL_RES(_name, _res) \
MFD_CELL_ALL(_name, _res, NULL, 0, 0, NULL, NULL) \
#define MFD_CELL_NAME(_name) \
MFD_CELL_ALL(_name, NULL, NULL, 0, 0, NULL, NULL) \
struct irq_domain; struct irq_domain;
struct property_entry; struct property_entry;
@ -30,8 +59,6 @@ struct mfd_cell {
const char *name; const char *name;
int id; int id;
/* refcounting for multiple drivers to use a single cell */
atomic_t *usage_count;
int (*enable)(struct platform_device *dev); int (*enable)(struct platform_device *dev);
int (*disable)(struct platform_device *dev); int (*disable)(struct platform_device *dev);
@ -86,24 +113,6 @@ struct mfd_cell {
extern int mfd_cell_enable(struct platform_device *pdev); extern int mfd_cell_enable(struct platform_device *pdev);
extern int mfd_cell_disable(struct platform_device *pdev); extern int mfd_cell_disable(struct platform_device *pdev);
/*
* "Clone" multiple platform devices for a single cell. This is to be used
* for devices that have multiple users of a cell. For example, if an mfd
* driver wants the cell "foo" to be used by a GPIO driver, an MTD driver,
* and a platform driver, the following bit of code would be use after first
* calling mfd_add_devices():
*
* const char *fclones[] = { "foo-gpio", "foo-mtd" };
* err = mfd_clone_cells("foo", fclones, ARRAY_SIZE(fclones));
*
* Each driver (MTD, GPIO, and platform driver) would then register
* platform_drivers for "foo-mtd", "foo-gpio", and "foo", respectively.
* The cell's .enable/.disable hooks should be used to deal with hardware
* resource contention.
*/
extern int mfd_clone_cell(const char *cell, const char **clones,
size_t n_clones);
/* /*
* Given a platform device that's been created by mfd_add_devices(), fetch * Given a platform device that's been created by mfd_add_devices(), fetch
* the mfd_cell that created it. * the mfd_cell that created it.

View File

@ -489,7 +489,7 @@ struct prcmu_auto_pm_config {
#ifdef CONFIG_MFD_DB8500_PRCMU #ifdef CONFIG_MFD_DB8500_PRCMU
void db8500_prcmu_early_init(u32 phy_base, u32 size); void db8500_prcmu_early_init(void);
int prcmu_set_rc_a2p(enum romcode_write); int prcmu_set_rc_a2p(enum romcode_write);
enum romcode_read prcmu_get_rc_p2a(void); enum romcode_read prcmu_get_rc_p2a(void);
enum ap_pwrst prcmu_get_xp70_current_state(void); enum ap_pwrst prcmu_get_xp70_current_state(void);
@ -546,7 +546,7 @@ void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value);
#else /* !CONFIG_MFD_DB8500_PRCMU */ #else /* !CONFIG_MFD_DB8500_PRCMU */
static inline void db8500_prcmu_early_init(u32 phy_base, u32 size) {} static inline void db8500_prcmu_early_init(void) {}
static inline int prcmu_set_rc_a2p(enum romcode_write code) static inline int prcmu_set_rc_a2p(enum romcode_write code)
{ {

View File

@ -190,6 +190,7 @@ enum ddr_pwrst {
#define PRCMU_FW_PROJECT_U8500_MBL2 12 /* Customer specific */ #define PRCMU_FW_PROJECT_U8500_MBL2 12 /* Customer specific */
#define PRCMU_FW_PROJECT_U8520 13 #define PRCMU_FW_PROJECT_U8520 13
#define PRCMU_FW_PROJECT_U8420 14 #define PRCMU_FW_PROJECT_U8420 14
#define PRCMU_FW_PROJECT_U8420_SYSCLK 17
#define PRCMU_FW_PROJECT_A9420 20 #define PRCMU_FW_PROJECT_A9420 20
/* [32..63] 9540 and derivatives */ /* [32..63] 9540 and derivatives */
#define PRCMU_FW_PROJECT_U9540 32 #define PRCMU_FW_PROJECT_U9540 32
@ -211,9 +212,9 @@ struct prcmu_fw_version {
#if defined(CONFIG_UX500_SOC_DB8500) #if defined(CONFIG_UX500_SOC_DB8500)
static inline void prcmu_early_init(u32 phy_base, u32 size) static inline void prcmu_early_init(void)
{ {
return db8500_prcmu_early_init(phy_base, size); return db8500_prcmu_early_init();
} }
static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk, static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
@ -401,7 +402,7 @@ static inline int prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
} }
#else #else
static inline void prcmu_early_init(u32 phy_base, u32 size) {} static inline void prcmu_early_init(void) {}
static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk, static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
bool keep_ap_pll) bool keep_ap_pll)

View File

@ -8,6 +8,7 @@
#ifndef MADERA_CORE_H #ifndef MADERA_CORE_H
#define MADERA_CORE_H #define MADERA_CORE_H
#include <linux/clk.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/mfd/madera/pdata.h> #include <linux/mfd/madera/pdata.h>
@ -29,6 +30,13 @@ enum madera_type {
CS42L92 = 9, CS42L92 = 9,
}; };
enum {
MADERA_MCLK1,
MADERA_MCLK2,
MADERA_MCLK3,
MADERA_NUM_MCLK
};
#define MADERA_MAX_CORE_SUPPLIES 2 #define MADERA_MAX_CORE_SUPPLIES 2
#define MADERA_MAX_GPIOS 40 #define MADERA_MAX_GPIOS 40
@ -155,6 +163,7 @@ struct snd_soc_dapm_context;
* @irq_dev: the irqchip child driver device * @irq_dev: the irqchip child driver device
* @irq_data: pointer to irqchip data for the child irqchip driver * @irq_data: pointer to irqchip data for the child irqchip driver
* @irq: host irq number from SPI or I2C configuration * @irq: host irq number from SPI or I2C configuration
* @mclk: Structure holding clock supplies
* @out_clamp: indicates output clamp state for each analogue output * @out_clamp: indicates output clamp state for each analogue output
* @out_shorted: indicates short circuit state for each analogue output * @out_shorted: indicates short circuit state for each analogue output
* @hp_ena: bitflags of enable state for the headphone outputs * @hp_ena: bitflags of enable state for the headphone outputs
@ -184,6 +193,8 @@ struct madera {
struct regmap_irq_chip_data *irq_data; struct regmap_irq_chip_data *irq_data;
int irq; int irq;
struct clk_bulk_data mclk[MADERA_NUM_MCLK];
unsigned int num_micbias; unsigned int num_micbias;
unsigned int num_childbias[MADERA_MAX_MICBIAS]; unsigned int num_childbias[MADERA_MAX_MICBIAS];

View File

@ -329,7 +329,6 @@ struct max77620_chip {
struct regmap *rmap; struct regmap *rmap;
int chip_irq; int chip_irq;
int irq_base;
/* chip id */ /* chip id */
enum max77620_chip_id chip_id; enum max77620_chip_id chip_id;

View File

@ -0,0 +1,71 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2014-2019 MediaTek Inc.
*
* Author: Tianping.Fang <tianping.fang@mediatek.com>
* Sean Wang <sean.wang@mediatek.com>
*/
#ifndef _LINUX_MFD_MT6397_RTC_H_
#define _LINUX_MFD_MT6397_RTC_H_
#include <linux/jiffies.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
#include <linux/rtc.h>
#define RTC_BBPU 0x0000
#define RTC_BBPU_CBUSY BIT(6)
#define RTC_BBPU_KEY (0x43 << 8)
#define RTC_WRTGR 0x003c
#define RTC_IRQ_STA 0x0002
#define RTC_IRQ_STA_AL BIT(0)
#define RTC_IRQ_STA_LP BIT(3)
#define RTC_IRQ_EN 0x0004
#define RTC_IRQ_EN_AL BIT(0)
#define RTC_IRQ_EN_ONESHOT BIT(2)
#define RTC_IRQ_EN_LP BIT(3)
#define RTC_IRQ_EN_ONESHOT_AL (RTC_IRQ_EN_ONESHOT | RTC_IRQ_EN_AL)
#define RTC_AL_MASK 0x0008
#define RTC_AL_MASK_DOW BIT(4)
#define RTC_TC_SEC 0x000a
/* Min, Hour, Dom... register offset to RTC_TC_SEC */
#define RTC_OFFSET_SEC 0
#define RTC_OFFSET_MIN 1
#define RTC_OFFSET_HOUR 2
#define RTC_OFFSET_DOM 3
#define RTC_OFFSET_DOW 4
#define RTC_OFFSET_MTH 5
#define RTC_OFFSET_YEAR 6
#define RTC_OFFSET_COUNT 7
#define RTC_AL_SEC 0x0018
#define RTC_PDN2 0x002e
#define RTC_PDN2_PWRON_ALARM BIT(4)
#define RTC_MIN_YEAR 1968
#define RTC_BASE_YEAR 1900
#define RTC_NUM_YEARS 128
#define RTC_MIN_YEAR_OFFSET (RTC_MIN_YEAR - RTC_BASE_YEAR)
#define MTK_RTC_POLL_DELAY_US 10
#define MTK_RTC_POLL_TIMEOUT (jiffies_to_usecs(HZ))
struct mt6397_rtc {
struct device *dev;
struct rtc_device *rtc_dev;
/* Protect register access from multiple tasks */
struct mutex lock;
struct regmap *regmap;
int irq;
u32 addr_base;
};
#endif /* _LINUX_MFD_MT6397_RTC_H_ */

View File

@ -610,7 +610,7 @@ enum {
RK808_ID = 0x0000, RK808_ID = 0x0000,
RK809_ID = 0x8090, RK809_ID = 0x8090,
RK817_ID = 0x8170, RK817_ID = 0x8170,
RK818_ID = 0x8181, RK818_ID = 0x8180,
}; };
struct rk808 { struct rk808 {

View File

@ -181,14 +181,18 @@ static inline int twl_i2c_read_u8(u8 mod_no, u8 *val, u8 reg) {
} }
static inline int twl_i2c_write_u16(u8 mod_no, u16 val, u8 reg) { static inline int twl_i2c_write_u16(u8 mod_no, u16 val, u8 reg) {
val = cpu_to_le16(val); __le16 value;
return twl_i2c_write(mod_no, (u8*) &val, reg, 2);
value = cpu_to_le16(val);
return twl_i2c_write(mod_no, (u8 *) &value, reg, 2);
} }
static inline int twl_i2c_read_u16(u8 mod_no, u16 *val, u8 reg) { static inline int twl_i2c_read_u16(u8 mod_no, u16 *val, u8 reg) {
int ret; int ret;
ret = twl_i2c_read(mod_no, (u8*) val, reg, 2); __le16 value;
*val = le16_to_cpu(*val);
ret = twl_i2c_read(mod_no, (u8 *) &value, reg, 2);
*val = le16_to_cpu(value);
return ret; return ret;
} }

View File

@ -9,6 +9,7 @@
enum devm_ioremap_type { enum devm_ioremap_type {
DEVM_IOREMAP = 0, DEVM_IOREMAP = 0,
DEVM_IOREMAP_NC, DEVM_IOREMAP_NC,
DEVM_IOREMAP_UC,
DEVM_IOREMAP_WC, DEVM_IOREMAP_WC,
}; };
@ -39,6 +40,9 @@ static void __iomem *__devm_ioremap(struct device *dev, resource_size_t offset,
case DEVM_IOREMAP_NC: case DEVM_IOREMAP_NC:
addr = ioremap_nocache(offset, size); addr = ioremap_nocache(offset, size);
break; break;
case DEVM_IOREMAP_UC:
addr = ioremap_uc(offset, size);
break;
case DEVM_IOREMAP_WC: case DEVM_IOREMAP_WC:
addr = ioremap_wc(offset, size); addr = ioremap_wc(offset, size);
break; break;
@ -68,6 +72,21 @@ void __iomem *devm_ioremap(struct device *dev, resource_size_t offset,
} }
EXPORT_SYMBOL(devm_ioremap); EXPORT_SYMBOL(devm_ioremap);
/**
* devm_ioremap_uc - Managed ioremap_uc()
* @dev: Generic device to remap IO address for
* @offset: Resource address to map
* @size: Size of map
*
* Managed ioremap_uc(). Map is automatically unmapped on driver detach.
*/
void __iomem *devm_ioremap_uc(struct device *dev, resource_size_t offset,
resource_size_t size)
{
return __devm_ioremap(dev, offset, size, DEVM_IOREMAP_UC);
}
EXPORT_SYMBOL_GPL(devm_ioremap_uc);
/** /**
* devm_ioremap_nocache - Managed ioremap_nocache() * devm_ioremap_nocache - Managed ioremap_nocache()
* @dev: Generic device to remap IO address for * @dev: Generic device to remap IO address for