Add support for Cirrus Logic CS47L35/L85/L90/L91 codecs
Subsystems (5)
Richard Fitzgerald
maintainerv9 cover Add support for Cirrus Logic CS47L35/L85/L90/L91 codecs
NOTE: Compared to older versions of this chain I have removed patches at the end of the chain that were being ignored until the earlier patches had been merged - an impossible circular dependency. There were too many moving targets to keep the whole chain up-to-date and so patches that were already acked were getting stale. The subset of patches here are all acked or close-to-acked, and can be built and used as they are to produce a working pinctrl and gpio.
The Cirrus Logic CS47L35, CS47L85, CS47L90/91 codecs are complex audio SoC devices. In addition to the core audio capability they have onboard GPIO, regulators, DSPs and interrupt controller and a large register map space accessed over SPI or I2C. This family of codecs is based around common IP blocks and they are managed by a set of common drivers referred to as "Madera".
Richard Fitzgerald (9):
mfd: madera: Add register definitions for Cirrus Logic Madera codecs
mfd: madera: Add DT bindings for Cirrus Logic Madera codecs
mfd: madera: Add common support for Cirrus Logic Madera codecs
mfd: madera: Register map tables for Cirrus Logic CS47L35
mfd: madera: Register map tables for Cirrus Logic CS47L85
mfd: madera: Register map tables for Cirrus Logic CS47L90/91
pinctrl: madera: Add DT bindings for Cirrus Logic Madera codecs
pinctrl: madera: Add driver for Cirrus Logic Madera codecs
gpio: madera: Support Cirrus Logic Madera class codecs
Documentation/devicetree/bindings/mfd/madera.txt | 102 + .../bindings/pinctrl/cirrus,madera-pinctrl.txt | 99 + MAINTAINERS | 16 + drivers/gpio/Kconfig | 6 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-madera.c | 206 + drivers/mfd/Kconfig | 50 + drivers/mfd/Makefile | 14 + drivers/mfd/cs47l35-tables.c | 1609 ++++++++ drivers/mfd/cs47l85-tables.c | 3009 +++++++++++++++ drivers/mfd/cs47l90-tables.c | 2674 +++++++++++++ drivers/mfd/madera-core.c | 600 +++ drivers/mfd/madera-i2c.c | 139 + drivers/mfd/madera-spi.c | 138 + drivers/mfd/madera.h | 44 + drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/cirrus/Kconfig | 15 + drivers/pinctrl/cirrus/Makefile | 13 + drivers/pinctrl/cirrus/pinctrl-cs47l35.c | 45 + drivers/pinctrl/cirrus/pinctrl-cs47l85.c | 59 + drivers/pinctrl/cirrus/pinctrl-cs47l90.c | 57 + drivers/pinctrl/cirrus/pinctrl-madera-core.c | 1074 ++++++ drivers/pinctrl/cirrus/pinctrl-madera.h | 41 + include/linux/mfd/madera/core.h | 187 + include/linux/mfd/madera/pdata.h | 63 + include/linux/mfd/madera/registers.h | 3917 ++++++++++++++++++++ 27 files changed, 14180 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/madera.txt create mode 100644 Documentation/devicetree/bindings/pinctrl/cirrus,madera-pinctrl.txt create mode 100644 drivers/gpio/gpio-madera.c create mode 100644 drivers/mfd/cs47l35-tables.c create mode 100644 drivers/mfd/cs47l85-tables.c create mode 100644 drivers/mfd/cs47l90-tables.c create mode 100644 drivers/mfd/madera-core.c create mode 100644 drivers/mfd/madera-i2c.c create mode 100644 drivers/mfd/madera-spi.c create mode 100644 drivers/mfd/madera.h create mode 100644 drivers/pinctrl/cirrus/Kconfig create mode 100644 drivers/pinctrl/cirrus/Makefile create mode 100644 drivers/pinctrl/cirrus/pinctrl-cs47l35.c create mode 100644 drivers/pinctrl/cirrus/pinctrl-cs47l85.c create mode 100644 drivers/pinctrl/cirrus/pinctrl-cs47l90.c create mode 100644 drivers/pinctrl/cirrus/pinctrl-madera-core.c create mode 100644 drivers/pinctrl/cirrus/pinctrl-madera.h create mode 100644 include/linux/mfd/madera/core.h create mode 100644 include/linux/mfd/madera/pdata.h create mode 100644 include/linux/mfd/madera/registers.h
Signature · 1 line
2.11.0
Richard Fitzgerald
maintainerPATCH v9 1/9 mfd: madera: Add register definitions for Cirrus Logic Madera codecs
This patch adds a header file of register definitions for Cirrus Logic "Madera" class codecs. These codecs are all based off a common set of hardware IP so have a common register map (with a few minor device-to-device variations).
The registers.h file is tool-generated directly from the hardware design but has been manually stripped down to reduce size (full register map is >44000 lines). All names are kept the same as datasheet names so that they can be cross-referenced between source and datasheet without confusion.
The register map layout is kept fully-defined rather than factored into macros and/or block-indexing code. The major reasons for this are:
- #1 is that it makes the source highly greppable, which is important. "What does the driver do with register bits XYZ" or "Where does it use register bits XYZ" are commonly types of questions. These can be quickly answered by a grep. Squashing definitions into generator macros or block- indexing code is a way of defeating grep.
- most of the register definitions are used in tables, so a constant value is required. Using generator macros make the table definition clunky and obscure.
- the code is clearer when it's there in the source exactly what register and field it is using
- it is easier to diff the register map of a new (unsupported) codec against what is already supported and merge in differences
- it makes the register map available in source for maintenance/debugging instead of having to refer back to the datasheet for a register map
--- MAINTAINERS | 10 + include/linux/mfd/madera/registers.h | 3917 ++++++++++++++++++++++++++++++++++ 2 files changed, 3927 insertions(+) create mode 100644 include/linux/mfd/madera/registers.h
MAINTAINERS +10 -0
@@ -3490,6 +3490,16 @@ M: Dave Goodell <[email protected]> S: Supported F: drivers/infiniband/hw/usnic/ +CIRRUS LOGIC MADERA CODEC DRIVERS +M: Charles Keepax <[email protected]> +M: Richard Fitzgerald <[email protected]> +L: [email protected] (moderated for non-subscribers) +L: [email protected] +T: git https://github.com/CirrusLogic/linux-drivers.git +W: https://github.com/CirrusLogic/linux-drivers/wiki +S: Supported +F: include/linux/mfd/madera/* + CLEANCACHE API M: Konrad Rzeszutek Wilk <[email protected]> L: [email protected]
include/linux/mfd/madera/registers.h new file +3917 -0
2,984 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Signature · 1 line
2.11.0
Part of the diff is not shown here. View the raw message.
Richard Fitzgerald
maintainerPATCH v9 2/9 mfd: madera: Add DT bindings for Cirrus Logic Madera codecs
In reply to Richard FitzgeraldSpecification of the bindings for the parent MFD driver component of the Cirrus Logic Madera codec drivers.
Note that although the interrupt controller and GPIO are child drivers their required bindings are trivial, mandatory, and exist within the parent MFD node so are documented here.
--- Documentation/devicetree/bindings/mfd/madera.txt | 102 +++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/madera.txt
Documentation/devicetree/bindings/mfd/madera.txt new file +102 -0
@@ -0,0 +1,102 @@ +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>; +};
Signature · 1 line
2.11.0
Richard Fitzgerald
maintainerPATCH v9 3/9 mfd: madera: Add common support for Cirrus Logic Madera codecs
In reply to Richard FitzgeraldThis adds the generic core support for Cirrus Logic "Madera" class codecs. These are complex audio codec SoCs with a variety of digital and analogue I/O, onboard audio processing and DSPs, and other features.
These codecs are all based off a common set of hardware IP so can be supported by a core of common code (with a few minor device-to-device variations).
---
There have been various smallish changes since Lee acked this patch so I have decided to err on the side of caution and remove the Ack in case Lee might have some comments about the current state of the code.
Cumulative changes since Lee acked it:
- changed to use gpiod for all reset code - affects madera_[enable|disable]_hard_reset, madera_get_reset_gpio, madera_dev_init
- use of_device_get_match_data in the spi and i2c probes
- use __maybe_unused on the pm runtime functions instead of a #ifdef
- don't put comma after {} list terminators
- commented why we don't use the devm version of mfd_add_devices
- don't use regulator_get_exclusive, it fails in the legitimate case of having the same regulator supply multiple chip supplies
- the core driver can now be built as a module
- minor Kconfig change to make the SPI/I2C submodules depend on the core module as this gives a more user-friendly menuconfig
- changed the irqchip and codec pdata to be a pointer to remove the build dependency so we can submit this patch without the irqchip and codec driver patches
- SPDX license headers
--- MAINTAINERS | 3 + drivers/mfd/Kconfig | 29 ++ drivers/mfd/Makefile | 5 + drivers/mfd/madera-core.c | 600 +++++++++++++++++++++++++++++++++++++++ drivers/mfd/madera-i2c.c | 139 +++++++++ drivers/mfd/madera-spi.c | 138 +++++++++ drivers/mfd/madera.h | 44 +++ include/linux/mfd/madera/core.h | 187 ++++++++++++ include/linux/mfd/madera/pdata.h | 63 ++++ 9 files changed, 1208 insertions(+) create mode 100644 drivers/mfd/madera-core.c create mode 100644 drivers/mfd/madera-i2c.c create mode 100644 drivers/mfd/madera-spi.c create mode 100644 drivers/mfd/madera.h create mode 100644 include/linux/mfd/madera/core.h create mode 100644 include/linux/mfd/madera/pdata.h
MAINTAINERS +3 -0
@@ -3498,7 +3498,10 @@ L: [email protected] 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: include/linux/mfd/madera/* +F: drivers/mfd/madera* +F: drivers/mfd/cs47l* CLEANCACHE API M: Konrad Rzeszutek Wilk <[email protected]>
drivers/mfd/Kconfig +29 -0
@@ -232,6 +232,35 @@ config MFD_CROS_EC_CHARDEV If you have a supported Chromebook, choose Y or M here. 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_ASIC3 bool "Compaq ASIC3" depends on GPIOLIB && ARM
drivers/mfd/Makefile +5 -0
@@ -72,6 +72,11 @@ wm8994-objs := wm8994-core.o wm8994-irq.o wm8994-regmap.o obj-$(CONFIG_MFD_WM8994) += wm8994.o obj-$(CONFIG_MFD_WM97xx) += wm97xx-core.o +madera-objs := madera-core.o +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_TPS65010) += tps65010.o obj-$(CONFIG_TPS6507X) += tps6507x.o
drivers/mfd/madera-core.c new file +600 -0
600 lines not on this page · raw message
drivers/mfd/madera-i2c.c new file +139 -0
139 lines not on this page · raw message
drivers/mfd/madera-spi.c new file +138 -0
138 lines not on this page · raw message
drivers/mfd/madera.h new file +44 -0
44 lines not on this page · raw message
include/linux/mfd/madera/core.h new file +187 -0
187 lines not on this page · raw message
include/linux/mfd/madera/pdata.h new file +63 -0
63 lines not on this page · raw message
Signature · 1 line
2.11.0
Re: [PATCH v9 3/9] mfd: madera: Add common support for Cirrus Logic Madera codecs
Quoted 276 lines · Richard Fitzgerald
This adds the generic core support for Cirrus Logic "Madera" class codecs. These are complex audio codec SoCs with a variety of digital and analogue I/O, onboard audio processing and DSPs, and other features.
These codecs are all based off a common set of hardware IP so can be supported by a core of common code (with a few minor device-to-device variations).
Signed-off-by Charles Keepax <[email protected]>Signed-off-by Nikesh Oswal <[email protected]>Signed-off-by Richard Fitzgerald <[email protected]>---
There have been various smallish changes since Lee acked this patch so I have decided to err on the side of caution and remove the Ack in case Lee might have some comments about the current state of the code.Cumulative changes since Lee acked it:
- changed to use gpiod for all reset code - affects madera_[enable|disable]_hard_reset,madera_get_reset_gpio,madera_dev_init
- useof_device_get_match_datain the spi and i2c probes
- use__maybe_unusedon the pm runtime functions instead of a #ifdef
- don't put comma after {} list terminators
- commented why we don't use the devm version ofmfd_add_devices
- don't useregulator_get_exclusive, it fails in the legitimate case of having the same regulator supply multiple chip supplies
- the core driver can now be built as a module
- minorKconfigchange to make the SPI/I2C submodules depend on the core module as this gives a more user-friendly menuconfig
- changed the irqchip and codec pdata to be a pointer to remove the build dependency so we can submit this patch without the irqchip and codec driver patches
- SPDX license headers--- MAINTAINERS | 3 + drivers/mfd/Kconfig | 29 ++ drivers/mfd/Makefile | 5 + drivers/mfd/madera-core.c | 600 +++++++++++++++++++++++++++++++++++++++ drivers/mfd/madera-i2c.c | 139 +++++++++ drivers/mfd/madera-spi.c | 138 +++++++++ drivers/mfd/madera.h | 44 +++ include/linux/mfd/madera/core.h | 187 ++++++++++++ include/linux/mfd/madera/pdata.h | 63 ++++ 9 files changed, 1208 insertions(+) create mode 100644 drivers/mfd/madera-core.c create mode 100644 drivers/mfd/madera-i2c.c create mode 100644 drivers/mfd/madera-spi.c create mode 100644 drivers/mfd/madera.h create mode 100644 include/linux/mfd/madera/core.h create mode 100644 include/linux/mfd/madera/pdata.hMAINTAINERS +3
-0@@ -3498,7 +3498,10 @@ L: [email protected] 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: include/linux/mfd/madera/* +F: drivers/mfd/madera* +F: drivers/mfd/cs47l* CLEANCACHE API M: Konrad Rzeszutek Wilk <[email protected]>drivers/mfd/Kconfig +29
-0@@ -232,6 +232,35 @@ config MFD_CROS_EC_CHARDEV If you have a supported Chromebook, choose Y or M here. 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_ASIC3 bool "Compaq ASIC3" depends on GPIOLIB && ARMdrivers/mfd/Makefile +5
-0@@ -72,6 +72,11 @@ wm8994-objs := wm8994-core.o wm8994-irq.o wm8994-regmap.o obj-$(CONFIG_MFD_WM8994) += wm8994.o obj-$(CONFIG_MFD_WM97xx) += wm97xx-core.o +madera-objs := madera-core.o +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_TPS65010) += tps65010.o obj-$(CONFIG_TPS6507X) += tps6507x.odrivers/mfd/madera-core.c new file +150
-0@@ -0,0 +1,600 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Core MFD 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/device.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/mfd/core.h> +#include <linux/module.h> +#include <linux/notifier.h> +#include <linux/of.h> +#include <linux/of_gpio.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> + +#include <linux/mfd/madera/core.h> +#include <linux/mfd/madera/registers.h> + +#include "madera.h" + +#define CS47L35_SILICON_ID 0x6360 +#define CS47L85_SILICON_ID 0x6338 +#define CS47L90_SILICON_ID 0x6364 + +#define MADERA_32KZ_MCLK2 1 + +static const char *const madera_core_supplies[] = { +"AVDD" , +"DBVDD1" , +}; + +static const struct mfd_cell madera_ldo1_devs[] = { + { .name ="madera-ldo1" }, +}; + +static const char *const cs47l35_supplies[] = { +"MICVDD" , +"DBVDD2" , +"CPVDD1" , +"CPVDD2" , +"SPKVDD" , +}; + +static const struct mfd_cell cs47l35_devs[] = { + { .name ="madera-pinctrl" , }, + { .name ="madera-irq" , }, + { .name ="madera-micsupp" , }, + { .name ="madera-gpio" , }, + { .name ="madera-extcon" , }, + { + .name ="cs47l35-codec" , + .parent_supplies = cs47l35_supplies, + .num_parent_supplies =ARRAY_SIZE (cs47l35_supplies), + }, +}; + +static const char *const cs47l85_supplies[] = { +"MICVDD" , +"DBVDD2" , +"DBVDD3" , +"DBVDD4" , +"CPVDD1" , +"CPVDD2" , +"SPKVDDL" , +"SPKVDDR" , +}; + +static const struct mfd_cell cs47l85_devs[] = { + { .name ="madera-pinctrl" , }, + { .name ="madera-irq" , }, + { .name ="madera-micsupp" }, + { .name ="madera-gpio" , }, + { .name ="madera-extcon" , }, + { + .name ="cs47l85-codec" , + .parent_supplies = cs47l85_supplies, + .num_parent_supplies =ARRAY_SIZE (cs47l85_supplies), + }, +}; + +static const char *const cs47l90_supplies[] = { +"MICVDD" , +"DBVDD2" , +"DBVDD3" , +"DBVDD4" , +"CPVDD1" , +"CPVDD2" , +}; + +static const struct mfd_cell cs47l90_devs[] = { + { .name ="madera-pinctrl" , }, + { .name ="madera-irq" , }, + { .name ="madera-micsupp" , }, + { .name ="madera-gpio" , }, + { .name ="madera-extcon" , }, + { + .name ="cs47l90-codec" , + .parent_supplies = cs47l90_supplies, + .num_parent_supplies =ARRAY_SIZE (cs47l90_supplies), + }, +}; + +/* Used by madera-i2c and madera-spi drivers */ +const char *madera_name_from_type (enum madera_type type) +{ +switch (type) { +case CS47L35 : +return "CS47L35" ; +case CS47L85 : +return "CS47L85" ; +case CS47L90 : +return "CS47L90" ; +case CS47L91 : +return "CS47L91" ; +case WM1840 : +return "WM1840" ; +default : +return "Unknown" ; + } +} +EXPORT_SYMBOL_GPL (madera_name_from_type); + +#define MADERA_BOOT_POLL_MAX_INTERVAL_US 5000 +#define MADERA_BOOT_POLL_TIMEOUT_US 25000 + +static int madera_wait_for_boot (struct madera *madera) +{ +unsigned int val; +int ret; + +/* +* We can't use an interrupt as we need to runtime resume to do so, +* so we poll the status bit. This won't race with the interrupt +* handler because it will be blocked on runtime resume. +*/ + ret = regmap_read_poll_timeout(madera->regmap, + MADERA_IRQ1_RAW_STATUS_1, + val,
drivers/mfd/madera-core.c line 160
Quoted 10 lines
drivers/mfd/madera-core.c new file +10
-0+ (val &MADERA_BOOT_DONE_STS1 ), +MADERA_BOOT_POLL_MAX_INTERVAL_US , + MADERA_BOOT_POLL_TIMEOUT_US); + +if (ret) +dev_err (madera->dev,"Polling BOOT_DONE_STS failed: %d\n" , ret); + +/* +* BOOT_DONE defaults to unmasked on boot so we must ack it. +* Do this unconditionally to avoid interrupt storms
Nit: Missing full stop
Quoted 22 lines
drivers/mfd/madera-core.c new file +22
-0+*/ +regmap_write (madera->regmap,MADERA_IRQ1_STATUS_1 , +MADERA_BOOT_DONE_EINT1 ); + +pm_runtime_mark_last_busy (madera->dev); + +return ret; +} + +static int madera_soft_reset (struct madera *madera) +{ +int ret; + + ret =regmap_write (madera->regmap,MADERA_SOFTWARE_RESET ,0 ); +if (ret !=0 ) { +dev_err (madera->dev,"Failed to soft reset device: %d\n" , ret); +return ret; + } + +/* Allow time for internal clocks to startup after reset */ +usleep_range (1000 ,2000 ); +
drivers/mfd/madera-core.c line 192
Quoted 10 lines
drivers/mfd/madera-core.c new file +10
-0+return 0 ; +} + +static void madera_enable_hard_reset (struct madera *madera) +{ +if (!madera->pdata.reset) +return ; + +/* +* there are many existing out-of-tree users of these codecs that we
Nit: There
Quoted 87 lines
drivers/mfd/madera-core.c new file +87
-0+* can't break so preserve the expected behaviour of setting the line +* low to assert reset +*/ +gpiod_set_raw_value_cansleep (madera->pdata.reset,0 ); +} + +static void madera_disable_hard_reset (struct madera *madera) +{ +if (!madera->pdata.reset) +return ; + +gpiod_set_raw_value_cansleep (madera->pdata.reset,1 ); +usleep_range (1000 ,2000 ); +} + +static int __maybe_unused madera_runtime_resume (struct device *dev) +{ +struct madera *madera =dev_get_drvdata (dev); +int ret; + +dev_dbg (dev,"Leaving sleep mode\n" ); + + ret =regulator_enable (madera->dcvdd); +if (ret) { +dev_err (dev,"Failed to enable DCVDD: %d\n" , ret); +return ret; + } + +regcache_cache_only (madera->regmap, false); +regcache_cache_only (madera->regmap_32bit, false); + + ret =madera_wait_for_boot (madera); +if (ret) + goto err; + + ret =regcache_sync (madera->regmap); +if (ret) { +dev_err (dev,"Failed to restore 16-bit register cache\n" ); + goto err; + } + + ret =regcache_sync (madera->regmap_32bit); +if (ret) { +dev_err (dev,"Failed to restore 32-bit register cache\n" ); + goto err; + } + +return 0 ; + +err: +regcache_cache_only (madera->regmap_32bit, true); +regcache_cache_only (madera->regmap, true); +regulator_disable (madera->dcvdd); + +return ret; +} + +static int __maybe_unused madera_runtime_suspend (struct device *dev) +{ +struct madera *madera =dev_get_drvdata (dev); + +dev_dbg (madera->dev,"Entering sleep mode\n" ); + +regcache_cache_only (madera->regmap, true); +regcache_mark_dirty (madera->regmap); +regcache_cache_only (madera->regmap_32bit, true); +regcache_mark_dirty (madera->regmap_32bit); + +regulator_disable (madera->dcvdd); + +return 0 ; +} + +const struct dev_pm_ops madera_pm_ops = { +SET_RUNTIME_PM_OPS (madera_runtime_suspend, + madera_runtime_resume, +NULL ) +}; +EXPORT_SYMBOL_GPL (madera_pm_ops); + +const struct of_device_id madera_of_match[] = { + { .compatible ="cirrus,cs47l35" , .data = (void *)CS47L35 }, + { .compatible ="cirrus,cs47l85" , .data = (void *)CS47L85 }, + { .compatible ="cirrus,cs47l90" , .data = (void *)CS47L90 }, + { .compatible ="cirrus,cs47l91" , .data = (void *)CS47L91 }, + { .compatible ="cirrus,wm1840" , .data = (void *)WM1840 }, + {}
drivers/mfd/madera-core.c line 289
Quoted 10 lines
drivers/mfd/madera-core.c new file +10
-0+}; +EXPORT_SYMBOL_GPL (madera_of_match); + +static int madera_get_reset_gpio (struct madera *madera) +{ +struct gpio_desc *reset; +int ret; + + reset =devm_gpiod_get_optional (madera->dev,"reset" ,GPIOD_OUT_LOW ); +
Nit: Remove this line.
drivers/mfd/madera-core.c line 292
Quoted 3 lines
drivers/mfd/madera-core.c new file +3
-0+if (IS_ERR (reset)) { + ret =PTR_ERR (reset); +if (ret == -EPROBE_DEFER )
Reverse the logic and only print the error if !-EPROBE_DEFER, then you only need one return.
Quoted 5 lines
drivers/mfd/madera-core.c new file +5
-0+return ret; + +dev_err (madera->dev,"Failed to request /RESET: %d\n" , ret); +return ret; + }
drivers/mfd/madera-core.c line 307
Quoted 10 lines
drivers/mfd/madera-core.c new file +10
-0+ + madera->pdata.reset = reset; + +return 0 ; +} + +static void madera_set_micbias_info (struct madera *madera) +{ +/* +* childbias is an array because future codecs can have different
You mean num_childbias?
drivers/mfd/madera-core.c line 318
Quoted 11 lines
drivers/mfd/madera-core.c new file +11
-0+* childbiases for each micbias +*/ +switch (madera->type) { +case CS47L35 : + madera->num_micbias =2 ; + madera->num_childbias[0 ] =2 ; + madera->num_childbias[1 ] =2 ; +return ; +case CS47L85 : +case WM1840 : + madera->num_micbias =4 ;
Where are the num_childbias[x] initialised for this device?
Quoted 19 lines
drivers/mfd/madera-core.c new file +19
-0+return ; +case CS47L90 : +case CS47L91 : + madera->num_micbias =2 ; + madera->num_childbias[0 ] =4 ; + madera->num_childbias[1 ] =4 ; +return ; +default : +return ; + } +} + +int madera_dev_init (struct madera *madera) +{ +struct device *dev = madera->dev; +unsigned int hwid; +int (*patch_fn)(struct madera *) =NULL ; +const struct mfd_cell *mfd_devs; +int n_devs =0 ;
drivers/mfd/madera-core.c line 347
Quoted 10 lines
drivers/mfd/madera-core.c new file +10
-0+int i, ret; + +dev_set_drvdata (madera->dev, madera); +BLOCKING_INIT_NOTIFIER_HEAD (&madera->notifier); +madera_set_micbias_info (madera); + +if (dev_get_platdata (madera->dev)) { +memcpy (&madera->pdata,dev_get_platdata (madera->dev), +sizeof (madera->pdata)); + }
Hmm... not sure about this.
Normally we extract what we need from pdata and place it into your ddata.
drivers/mfd/madera-core.c line 356
Quoted 8 lines
drivers/mfd/madera-core.c new file +8
-0+if (!madera->pdata.reset) { + ret =madera_get_reset_gpio (madera); +if (ret) +return ret; + } +if (!madera->pdata.reset) +dev_warn (madera->dev, +"Running without reset GPIO is not recommended\n" );
Is this even possible? If so, handle it in madera_get_reset_gpio().
Quoted 14 lines
drivers/mfd/madera-core.c new file +14
-0+regcache_cache_only (madera->regmap, true); +regcache_cache_only (madera->regmap_32bit, true); + +for (i =0 ; i <ARRAY_SIZE (madera_core_supplies); i++) + madera->core_supplies[i].supply = madera_core_supplies[i]; + + madera->num_core_supplies =ARRAY_SIZE (madera_core_supplies); + +/* +* On some codecs DCVDD could be supplied by the internal LDO1. +* For those we must add the LDO1 driver before requesting DCVDD +* No devm_ because we need to control shutdown order of children. +*/ +switch (madera->type) {
drivers/mfd/madera-core.c line 381
Quoted 10 lines
drivers/mfd/madera-core.c new file +10
-0+case CS47L35 : +case CS47L90 : +case CS47L91 : +break ; +case CS47L85 : +case WM1840 : + ret =mfd_add_devices (madera->dev,PLATFORM_DEVID_NONE , + madera_ldo1_devs, +ARRAY_SIZE (madera_ldo1_devs), +NULL ,0 ,NULL );
LEE: Is there any guarantee?
#########################################################
#########################################################
#########################################################
#########################################################
#########################################################
#########################################################
Quoted 14 lines
drivers/mfd/madera-core.c new file +14
-0+if (ret) { +dev_err (dev,"Failed to add LDO1 child: %d\n" , ret); +return ret; + } +break ; +default : +/* No point continuing if the type is unknown */ +dev_err (madera->dev,"Unknown device type %d\n" , madera->type); +return -ENODEV ; + } + + ret =devm_regulator_bulk_get (dev, madera->num_core_supplies, + madera->core_supplies); +if (ret) {
drivers/mfd/madera-core.c line 405
Quoted 10 lines
drivers/mfd/madera-core.c new file +10
-0+dev_err (dev,"Failed to request core supplies: %d\n" , ret); + goto err_devs; + } + +/* +* Don't use devres here because the only device we have to get +* against is the MFD device and DCVDD will likely be supplied by +* one of its children. Meaning that the regulator will be +* destroyed by the time devres calls regulator put. +*/
I'm confused. So the regulator you're *_get()ing doesn't exist yet?
Quoted 18 lines
drivers/mfd/madera-core.c new file +18
-0+ madera->dcvdd =regulator_get (madera->dev,"DCVDD" ); +if (IS_ERR (madera->dcvdd)) { + ret =PTR_ERR (madera->dcvdd); +dev_err (dev,"Failed to request DCVDD: %d\n" , ret); + goto err_devs; + } + + ret =regulator_bulk_enable (madera->num_core_supplies, + madera->core_supplies); +if (ret) { +dev_err (dev,"Failed to enable core supplies: %d\n" , ret); + goto err_dcvdd; + } + + ret =regulator_enable (madera->dcvdd); +if (ret) { +dev_err (dev,"Failed to enable DCVDD: %d\n" , ret); + goto err_enable;
drivers/mfd/madera-core.c line 433
Quoted 10 lines
drivers/mfd/madera-core.c new file +10
-0+ } + +madera_disable_hard_reset (madera); + +regcache_cache_only (madera->regmap, false); +regcache_cache_only (madera->regmap_32bit, false); + +/* +* Verify that this is a chip we know about before we +* starting doing any writes to its registers
Nit: start
Shouldn't you do this *before* you start to set everything up above?
drivers/mfd/madera-core.c line 433
Quoted 2 lines
drivers/mfd/madera-core.c new file +2
-0+*/ + ret =regmap_read (madera->regmap,MADERA_SOFTWARE_RESET , &hwid);
MADERA_SOFTWARE_RESET ?
drivers/mfd/madera-core.c line 446
Quoted 11 lines
drivers/mfd/madera-core.c new file +11
-0+if (ret) { +dev_err (dev,"Failed to read ID register: %d\n" , ret); + goto err_reset; + } + +switch (hwid) { +case CS47L35_SILICON_ID : +if (IS_ENABLED (CONFIG_MFD_CS47L35 )) { +switch (madera->type) { +case CS47L35 : + patch_fn = cs47l35_patch;
I've always hated these.
Why doesn't the device come with a sensible default configuration that you can sensibly adjust accordingly in a *sane* way?
Quoted 44 lines
drivers/mfd/madera-core.c new file +44
-0+ mfd_devs = cs47l35_devs; + n_devs =ARRAY_SIZE (cs47l35_devs); +break ; +default : +break ; + } + } +break ; +case CS47L85_SILICON_ID : +if (IS_ENABLED (CONFIG_MFD_CS47L85 )) { +switch (madera->type) { +case CS47L85 : +case WM1840 : + patch_fn = cs47l85_patch; + mfd_devs = cs47l85_devs; + n_devs =ARRAY_SIZE (cs47l85_devs); +break ; +default : +break ; + } + } +break ; +case CS47L90_SILICON_ID : +if (IS_ENABLED (CONFIG_MFD_CS47L90 )) { +switch (madera->type) { +case CS47L90 : +case CS47L91 : + patch_fn = cs47l90_patch; + mfd_devs = cs47l90_devs; + n_devs =ARRAY_SIZE (cs47l90_devs); +break ; +default : +break ; + } + } +break ; +default : +dev_err (madera->dev,"Unknown device ID: %x\n" , hwid); + ret = -EINVAL ; + goto err_reset; + } + +if (!n_devs) { + dev_err(madera->dev, "Device ID 0x%x not a %s\n", hwid,
drivers/mfd/madera-core.c line 500
Quoted 10 lines
drivers/mfd/madera-core.c new file +10
-0+ madera->type_name); + ret = -ENODEV ; + goto err_reset; + } + +/* +* It looks like a device we support. If we don't have a hard reset +* we can now attempt a soft reset +*/ +if (!madera->pdata.reset) {
Call the reset regardless and do any affiliated checks *inside*.
Quoted 168 lines
drivers/mfd/madera-core.c new file +100
-0+ ret =madera_soft_reset (madera); +if (ret) + goto err_reset; + } + + ret =madera_wait_for_boot (madera); +if (ret) { +dev_err (madera->dev,"Device failed initial boot: %d\n" , ret); + goto err_reset; + } + + ret =regmap_read (madera->regmap,MADERA_HARDWARE_REVISION , + &madera->rev); +if (ret) { +dev_err (dev,"Failed to read revision register: %d\n" , ret); + goto err_reset; + } + madera->rev &=MADERA_HW_REVISION_MASK ; + +dev_info (dev,"%s silicon revision %d\n" , madera->type_name, + madera->rev); + +/* Apply hardware patch */ +if (patch_fn) { + ret =patch_fn (madera); +if (ret) { +dev_err (madera->dev,"Failed to apply patch %d\n" , ret); + goto err_reset; + } + } + +/* Init 32k clock sourced from MCLK2 */ + ret =regmap_update_bits (madera->regmap, +MADERA_CLOCK_32K_1 , +MADERA_CLK_32K_ENA_MASK |MADERA_CLK_32K_SRC_MASK , +MADERA_CLK_32K_ENA |MADERA_32KZ_MCLK2 ); +if (ret) { +dev_err (madera->dev,"Failed to init 32k clock: %d\n" , ret); + goto err_reset; + } + +pm_runtime_set_active (madera->dev); +pm_runtime_enable (madera->dev); +pm_runtime_set_autosuspend_delay (madera->dev,100 ); +pm_runtime_use_autosuspend (madera->dev); + +/* No devm_ because we need to control shutdown order of children */ + ret =mfd_add_devices (madera->dev,PLATFORM_DEVID_NONE , + mfd_devs, n_devs, +NULL ,0 ,NULL ); +if (ret) { +dev_err (madera->dev,"Failed to add subdevices: %d\n" , ret); + goto err_pm_runtime; + } + +return 0 ; + +err_pm_runtime: +pm_runtime_disable (madera->dev); +err_reset: +madera_enable_hard_reset (madera); +regulator_disable (madera->dcvdd); +err_enable: +regulator_bulk_disable (madera->num_core_supplies, + madera->core_supplies); +err_dcvdd: +regulator_put (madera->dcvdd); +err_devs: +mfd_remove_devices (dev); + +return ret; +} +EXPORT_SYMBOL_GPL (madera_dev_init); + +int madera_dev_exit (struct madera *madera) +{ +/* Prevent any IRQs being serviced while we clean up */ +disable_irq (madera->irq); + +/* +* DCVDD could be supplied by a child node, we must disable it before +* removing the children, and prevent PM runtime from turning it back on +*/ +pm_runtime_disable (madera->dev); + +regulator_disable (madera->dcvdd); +regulator_put (madera->dcvdd); + +mfd_remove_devices (madera->dev); +madera_enable_hard_reset (madera); + +regulator_bulk_disable (madera->num_core_supplies, + madera->core_supplies); +return 0 ; +} +EXPORT_SYMBOL_GPL (madera_dev_exit); + +MODULE_DESCRIPTION ("Madera core MFD driver" ); +MODULE_AUTHOR ("Richard Fitzgerald <[email protected]>" ); +MODULE_LICENSE ("GPL v2" );drivers/mfd/madera-i2c.c new file +62
-0@@ -0,0 +1,139 @@ +// 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 :
drivers/mfd/madera-i2c.c line 72
Quoted 10 lines
drivers/mfd/madera-i2c.c new file +10
-0+dev_err (&i2c->dev, +"Unknown Madera I2C device type %ld\n" , type); +return -EINVAL ; + } + + name =madera_name_from_type (type); + +if (!regmap_16bit_config) { +dev_err (&i2c->dev, +"Kernel does not include support for %s\n" , name);
So you have provided support for devices in madera_name_from_type(), but not elsewhere?
Quoted 135 lines
drivers/mfd/madera-i2c.c new file +67
-0+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 <[email protected]>" ); +MODULE_LICENSE ("GPL v2" );drivers/mfd/madera-spi.c new file +62
-0@@ -0,0 +1,138 @@ +// 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 :
drivers/mfd/madera-spi.c line 72
Quoted 10 lines
drivers/mfd/madera-spi.c new file +10
-0+dev_err (&spi->dev, +"Unknown Madera SPI device type %ld\n" , type); +return -EINVAL ; + } + + name =madera_name_from_type (type); + +if (!regmap_16bit_config) { +dev_err (&spi->dev, +"Kernel does not include support for %s\n" , name);
As above?
Quoted 366 lines
drivers/mfd/madera-spi.c new file +66
-0+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 <[email protected]>" ); +MODULE_LICENSE ("GPL v2" );drivers/mfd/madera.h new file +44
-0@@ -0,0 +1,44 @@ +/* +* 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 include/linux/mfd/madera/core.h new file +187
-0@@ -0,0 +1,187 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* MFD internals 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. +*/ + +#ifndef MADERA_CORE_H +#define MADERA_CORE_H + +#include <linux/gpio/consumer.h> +#include <linux/interrupt.h> +#include <linux/mfd/madera/pdata.h> +#include <linux/notifier.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> + +enum madera_type { +/* 0 is reserved for indicating failure to identify */ +CS47L35 =1 , +CS47L85 =2 , +CS47L90 =3 , +CS47L91 =4 , +WM1840 =7 , +}; + +#define MADERA_MAX_CORE_SUPPLIES 2 +#define MADERA_MAX_GPIOS 40 + +#define CS47L35_NUM_GPIOS 16 +#define CS47L85_NUM_GPIOS 40 +#define CS47L90_NUM_GPIOS 38 + +#define MADERA_MAX_MICBIAS 4 + +/* Notifier events */ +#define MADERA_NOTIFY_VOICE_TRIGGER 0x1 +#define MADERA_NOTIFY_HPDET 0x2 +#define MADERA_NOTIFY_MICDET 0x4 + +/* GPIO Function Definitions */ +#define MADERA_GP_FN_ALTERNATE 0x00 +#define MADERA_GP_FN_GPIO 0x01 +#define MADERA_GP_FN_DSP_GPIO 0x02 +#define MADERA_GP_FN_IRQ1 0x03 +#define MADERA_GP_FN_IRQ2 0x04 +#define MADERA_GP_FN_FLL1_CLOCK 0x10 +#define MADERA_GP_FN_FLL2_CLOCK 0x11 +#define MADERA_GP_FN_FLL3_CLOCK 0x12 +#define MADERA_GP_FN_FLLAO_CLOCK 0x13 +#define MADERA_GP_FN_FLL1_LOCK 0x18 +#define MADERA_GP_FN_FLL2_LOCK 0x19 +#define MADERA_GP_FN_FLL3_LOCK 0x1A +#define MADERA_GP_FN_FLLAO_LOCK 0x1B +#define MADERA_GP_FN_OPCLK_OUT 0x40 +#define MADERA_GP_FN_OPCLK_ASYNC_OUT 0x41 +#define MADERA_GP_FN_PWM1 0x48 +#define MADERA_GP_FN_PWM2 0x49 +#define MADERA_GP_FN_SPDIF_OUT 0x4C +#define MADERA_GP_FN_HEADPHONE_DET 0x50 +#define MADERA_GP_FN_MIC_DET 0x58 +#define MADERA_GP_FN_DRC1_SIGNAL_DETECT 0x80 +#define MADERA_GP_FN_DRC2_SIGNAL_DETECT 0x81 +#define MADERA_GP_FN_ASRC1_IN1_LOCK 0x88 +#define MADERA_GP_FN_ASRC1_IN2_LOCK 0x89 +#define MADERA_GP_FN_ASRC2_IN1_LOCK 0x8A +#define MADERA_GP_FN_ASRC2_IN2_LOCK 0x8B +#define MADERA_GP_FN_DSP_IRQ1 0xA0 +#define MADERA_GP_FN_DSP_IRQ2 0xA1 +#define MADERA_GP_FN_DSP_IRQ3 0xA2 +#define MADERA_GP_FN_DSP_IRQ4 0xA3 +#define MADERA_GP_FN_DSP_IRQ5 0xA4 +#define MADERA_GP_FN_DSP_IRQ6 0xA5 +#define MADERA_GP_FN_DSP_IRQ7 0xA6 +#define MADERA_GP_FN_DSP_IRQ8 0xA7 +#define MADERA_GP_FN_DSP_IRQ9 0xA8 +#define MADERA_GP_FN_DSP_IRQ10 0xA9 +#define MADERA_GP_FN_DSP_IRQ11 0xAA +#define MADERA_GP_FN_DSP_IRQ12 0xAB +#define MADERA_GP_FN_DSP_IRQ13 0xAC +#define MADERA_GP_FN_DSP_IRQ14 0xAD +#define MADERA_GP_FN_DSP_IRQ15 0xAE +#define MADERA_GP_FN_DSP_IRQ16 0xAF +#define MADERA_GP_FN_HPOUT1L_SC 0xB0 +#define MADERA_GP_FN_HPOUT1R_SC 0xB1 +#define MADERA_GP_FN_HPOUT2L_SC 0xB2 +#define MADERA_GP_FN_HPOUT2R_SC 0xB3 +#define MADERA_GP_FN_HPOUT3L_SC 0xB4 +#define MADERA_GP_FN_HPOUT4R_SC 0xB5 +#define MADERA_GP_FN_SPKOUTL_SC 0xB6 +#define MADERA_GP_FN_SPKOUTR_SC 0xB7 +#define MADERA_GP_FN_HPOUT1L_ENA 0xC0 +#define MADERA_GP_FN_HPOUT1R_ENA 0xC1 +#define MADERA_GP_FN_HPOUT2L_ENA 0xC2 +#define MADERA_GP_FN_HPOUT2R_ENA 0xC3 +#define MADERA_GP_FN_HPOUT3L_ENA 0xC4 +#define MADERA_GP_FN_HPOUT4R_ENA 0xC5 +#define MADERA_GP_FN_SPKOUTL_ENA 0xC6 +#define MADERA_GP_FN_SPKOUTR_ENA 0xC7 +#define MADERA_GP_FN_HPOUT1L_DIS 0xD0 +#define MADERA_GP_FN_HPOUT1R_DIS 0xD1 +#define MADERA_GP_FN_HPOUT2L_DIS 0xD2 +#define MADERA_GP_FN_HPOUT2R_DIS 0xD3 +#define MADERA_GP_FN_HPOUT3L_DIS 0xD4 +#define MADERA_GP_FN_HPOUT4R_DIS 0xD5 +#define MADERA_GP_FN_SPKOUTL_DIS 0xD6 +#define MADERA_GP_FN_SPKOUTR_DIS 0xD7 +#define MADERA_GP_FN_SPK_SHUTDOWN 0xE0 +#define MADERA_GP_FN_SPK_OVH_SHUTDOWN 0xE1 +#define MADERA_GP_FN_SPK_OVH_WARN 0xE2 +#define MADERA_GP_FN_TIMER1_STATUS 0x140 +#define MADERA_GP_FN_TIMER2_STATUS 0x141 +#define MADERA_GP_FN_TIMER3_STATUS 0x142 +#define MADERA_GP_FN_TIMER4_STATUS 0x143 +#define MADERA_GP_FN_TIMER5_STATUS 0x144 +#define MADERA_GP_FN_TIMER6_STATUS 0x145 +#define MADERA_GP_FN_TIMER7_STATUS 0x146 +#define MADERA_GP_FN_TIMER8_STATUS 0x147 +#define MADERA_GP_FN_EVENTLOG1_FIFO_STS 0x150 +#define MADERA_GP_FN_EVENTLOG2_FIFO_STS 0x151 +#define MADERA_GP_FN_EVENTLOG3_FIFO_STS 0x152 +#define MADERA_GP_FN_EVENTLOG4_FIFO_STS 0x153 +#define MADERA_GP_FN_EVENTLOG5_FIFO_STS 0x154 +#define MADERA_GP_FN_EVENTLOG6_FIFO_STS 0x155 +#define MADERA_GP_FN_EVENTLOG7_FIFO_STS 0x156 +#define MADERA_GP_FN_EVENTLOG8_FIFO_STS 0x157 + +struct snd_soc_dapm_context ; + +/* +* struct madera - internal data shared by the set of Madera drivers +* +* This should not be used by anything except child drivers of the Madera MFD +* +* @regmap: pointer to the regmap instance for 16-bit registers +* @regmap_32bit: pointer to the regmap instance for 32-bit registers +* @dev: pointer to the MFD device +* @type: type of codec +* @rev: silicon revision +* @type_name: display name of this codec +* @num_core_supplies: number of core supply regulators +* @core_supplies: list of core supplies that are always required +* @dcvdd: pointer to DCVDD regulator +* @internal_dcvdd: true if DCVDD is supplied from the internal LDO1 +* @pdata: our pdata +* @irq_dev: the irqchip child driver device +* @irq: host irq number from SPI or I2C configuration +* @out_clamp: indicates output clamp 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 +* @num_micbias: number of MICBIAS outputs +* @num_childbias: number of child biases for each MICBIAS +* @dapm: pointer to codec driver DAPM context +* @notifier: notifier for signalling events to ASoC machine driver +*/ +struct madera { +struct regmap *regmap; +struct regmap *regmap_32bit; + +struct device *dev; + +enum madera_type type; +unsigned int rev; +const char *type_name; + +int num_core_supplies; +struct regulator_bulk_data core_supplies[MADERA_MAX_CORE_SUPPLIES ]; +struct regulator *dcvdd; +bool internal_dcvdd; + +struct madera_pdata pdata; + +struct device *irq_dev; +int irq; + +unsigned int num_micbias; +unsigned int num_childbias[MADERA_MAX_MICBIAS ]; + +struct snd_soc_dapm_context *dapm; + +struct blocking_notifier_head notifier; +}; +#endif include/linux/mfd/madera/pdata.h new file +51
-0@@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Platform data 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. +*/ + +#ifndef MADERA_PDATA_H +#define MADERA_PDATA_H + +#include <linux/kernel.h> +#include <linux/regulator/arizona-ldo1.h> +#include <linux/regulator/arizona-micsupp.h> +#include <linux/regulator/machine.h> + +#define MADERA_MAX_MICBIAS 4 +#define MADERA_MAX_CHILD_MICBIAS 4 + +#define MADERA_MAX_GPSW 2 + +struct gpio_desc; +struct pinctrl_map; +struct madera_irqchip_pdata; +struct madera_codec_pdata; + +/** + * struct madera_pdata - Configuration data for Madera devices + * + * @reset: GPIO controlling /RESET (NULL = none) + * @ldo1: Substruct of pdata for the LDO1 regulator + * @micvdd: Substruct of pdata for the MICVDD regulator + * @irqchip: Pointer to optional pdata for the irqchip driver + * @gpio_base: Base GPIO number + * @gpio_configs: Array of GPIO configurations (See Documentation/pinctrl.txt) + * @n_gpio_configs: Number of entries in gpio_configs + * @codec: Pointer to optional pdata for the ASoC codec driver + * See include/sound/madera-pdata.h + * @gpsw: General purpose switch mode setting (See the SW1_MODE field + * in the datasheet for the available values for your codec) + */ +struct madera_pdata { + struct gpio_desc *reset; + + struct arizona_ldo1_pdata ldo1; + struct arizona_micsupp_pdata micvdd; + + struct madera_irqchip_pdata *irqchip;
include/linux/mfd/madera/pdata.h line 61
Quoted 10 lines
include/linux/mfd/madera/pdata.h new file +10
-0+ +int gpio_base; + +const struct pinctrl_map *gpio_configs; +int n_gpio_configs; + +struct madera_codec_pdata *codec; + +u32 gpsw[MADERA_MAX_GPSW ]; +};
This doesn't look like platform data. Where does it come from?
Quoted 1 line
include/linux/mfd/madera/pdata.h new file +1
-0+#endif
Signature · 4 lines
Lee Jones [李琼斯] Linaro Services Technical Lead Linaro.org │ Open source software for ARM SoCs Follow Linaro: Facebook | Twitter | Blog
Richard Fitzgerald
maintainerRe: [PATCH v9 3/9] mfd: madera: Add common support for Cirrus Logic Madera codecs
Quoted 451 lines · Lee Jones
Quoted 276 lines · Richard Fitzgerald
This adds the generic core support for Cirrus Logic "Madera" class codecs. These are complex audio codec SoCs with a variety of digital and analogue I/O, onboard audio processing and DSPs, and other features.
These codecs are all based off a common set of hardware IP so can be supported by a core of common code (with a few minor device-to-device variations).
Signed-off-by Charles Keepax <[email protected]>Signed-off-by Nikesh Oswal <[email protected]>Signed-off-by Richard Fitzgerald <[email protected]>---
There have been various smallish changes since Lee acked this patch so I have decided to err on the side of caution and remove the Ack in case Lee might have some comments about the current state of the code.Cumulative changes since Lee acked it:
- changed to use gpiod for all reset code - affects madera_[enable|disable]_hard_reset,madera_get_reset_gpio,madera_dev_init
- useof_device_get_match_datain the spi and i2c probes
- use__maybe_unusedon the pm runtime functions instead of a #ifdef
- don't put comma after {} list terminators
- commented why we don't use the devm version ofmfd_add_devices
- don't useregulator_get_exclusive, it fails in the legitimate case of having the same regulator supply multiple chip supplies
- the core driver can now be built as a module
- minorKconfigchange to make the SPI/I2C submodules depend on the core module as this gives a more user-friendly menuconfig
- changed the irqchip and codec pdata to be a pointer to remove the build dependency so we can submit this patch without the irqchip and codec driver patches
- SPDX license headers--- MAINTAINERS | 3 + drivers/mfd/Kconfig | 29 ++ drivers/mfd/Makefile | 5 + drivers/mfd/madera-core.c | 600 +++++++++++++++++++++++++++++++++++++++ drivers/mfd/madera-i2c.c | 139 +++++++++ drivers/mfd/madera-spi.c | 138 +++++++++ drivers/mfd/madera.h | 44 +++ include/linux/mfd/madera/core.h | 187 ++++++++++++ include/linux/mfd/madera/pdata.h | 63 ++++ 9 files changed, 1208 insertions(+)create mode 100644
drivers/mfd/madera-core.ccreate mode 100644drivers/mfd/madera-i2c.ccreate mode 100644drivers/mfd/madera-spi.ccreate mode 100644drivers/mfd/madera.hcreate mode 100644include/linux/mfd/madera/core.hcreate mode 100644include/linux/mfd/madera/pdata.hMAINTAINERS +3
-0@@ -3498,7 +3498,10 @@ L: [email protected] 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: include/linux/mfd/madera/* +F: drivers/mfd/madera* +F: drivers/mfd/cs47l* CLEANCACHE API M: Konrad Rzeszutek Wilk <[email protected]>drivers/mfd/Kconfig +29
-0@@ -232,6 +232,35 @@ config MFD_CROS_EC_CHARDEV If you have a supported Chromebook, choose Y or M here. 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_ASIC3 bool "Compaq ASIC3" depends on GPIOLIB && ARMdrivers/mfd/Makefile +5
-0@@ -72,6 +72,11 @@ wm8994-objs := wm8994-core.o wm8994-irq.o wm8994-regmap.o obj-$(CONFIG_MFD_WM8994) += wm8994.o obj-$(CONFIG_MFD_WM97xx) += wm97xx-core.o +madera-objs := madera-core.o +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_TPS65010) += tps65010.o obj-$(CONFIG_TPS6507X) += tps6507x.odrivers/mfd/madera-core.c new file +150
-0@@ -0,0 +1,600 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Core MFD 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/device.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/mfd/core.h> +#include <linux/module.h> +#include <linux/notifier.h> +#include <linux/of.h> +#include <linux/of_gpio.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> + +#include <linux/mfd/madera/core.h> +#include <linux/mfd/madera/registers.h> + +#include "madera.h" + +#define CS47L35_SILICON_ID 0x6360 +#define CS47L85_SILICON_ID 0x6338 +#define CS47L90_SILICON_ID 0x6364 + +#define MADERA_32KZ_MCLK2 1 + +static const char *const madera_core_supplies[] = { +"AVDD" , +"DBVDD1" , +}; + +static const struct mfd_cell madera_ldo1_devs[] = { + { .name ="madera-ldo1" }, +}; + +static const char *const cs47l35_supplies[] = { +"MICVDD" , +"DBVDD2" , +"CPVDD1" , +"CPVDD2" , +"SPKVDD" , +}; + +static const struct mfd_cell cs47l35_devs[] = { + { .name ="madera-pinctrl" , }, + { .name ="madera-irq" , }, + { .name ="madera-micsupp" , }, + { .name ="madera-gpio" , }, + { .name ="madera-extcon" , }, + { + .name ="cs47l35-codec" , + .parent_supplies = cs47l35_supplies, + .num_parent_supplies =ARRAY_SIZE (cs47l35_supplies), + }, +}; + +static const char *const cs47l85_supplies[] = { +"MICVDD" , +"DBVDD2" , +"DBVDD3" , +"DBVDD4" , +"CPVDD1" , +"CPVDD2" , +"SPKVDDL" , +"SPKVDDR" , +}; + +static const struct mfd_cell cs47l85_devs[] = { + { .name ="madera-pinctrl" , }, + { .name ="madera-irq" , }, + { .name ="madera-micsupp" }, + { .name ="madera-gpio" , }, + { .name ="madera-extcon" , }, + { + .name ="cs47l85-codec" , + .parent_supplies = cs47l85_supplies, + .num_parent_supplies =ARRAY_SIZE (cs47l85_supplies), + }, +}; + +static const char *const cs47l90_supplies[] = { +"MICVDD" , +"DBVDD2" , +"DBVDD3" , +"DBVDD4" , +"CPVDD1" , +"CPVDD2" , +}; + +static const struct mfd_cell cs47l90_devs[] = { + { .name ="madera-pinctrl" , }, + { .name ="madera-irq" , }, + { .name ="madera-micsupp" , }, + { .name ="madera-gpio" , }, + { .name ="madera-extcon" , }, + { + .name ="cs47l90-codec" , + .parent_supplies = cs47l90_supplies, + .num_parent_supplies =ARRAY_SIZE (cs47l90_supplies), + }, +}; + +/* Used by madera-i2c and madera-spi drivers */ +const char *madera_name_from_type (enum madera_type type) +{ +switch (type) { +case CS47L35 : +return "CS47L35" ; +case CS47L85 : +return "CS47L85" ; +case CS47L90 : +return "CS47L90" ; +case CS47L91 : +return "CS47L91" ; +case WM1840 : +return "WM1840" ; +default : +return "Unknown" ; + } +} +EXPORT_SYMBOL_GPL (madera_name_from_type); + +#define MADERA_BOOT_POLL_MAX_INTERVAL_US 5000 +#define MADERA_BOOT_POLL_TIMEOUT_US 25000 + +static int madera_wait_for_boot (struct madera *madera) +{ +unsigned int val; +int ret; + +/* +* We can't use an interrupt as we need to runtime resume to do so, +* so we poll the status bit. This won't race with the interrupt +* handler because it will be blocked on runtime resume. +*/ + ret = regmap_read_poll_timeout(madera->regmap, + MADERA_IRQ1_RAW_STATUS_1, + val,drivers/mfd/madera-core.c line 160
Quoted 10 lines
drivers/mfd/madera-core.c new file +10
-0+ (val &MADERA_BOOT_DONE_STS1 ), +MADERA_BOOT_POLL_MAX_INTERVAL_US , + MADERA_BOOT_POLL_TIMEOUT_US); + +if (ret) +dev_err (madera->dev,"Polling BOOT_DONE_STS failed: %d\n" , ret); + +/* +* BOOT_DONE defaults to unmasked on boot so we must ack it. +* Do this unconditionally to avoid interrupt storms Nit: Missing full stop
Quoted 22 lines
drivers/mfd/madera-core.c new file +22
-0+*/ +regmap_write (madera->regmap,MADERA_IRQ1_STATUS_1 , +MADERA_BOOT_DONE_EINT1 ); + +pm_runtime_mark_last_busy (madera->dev); + +return ret; +} + +static int madera_soft_reset (struct madera *madera) +{ +int ret; + + ret =regmap_write (madera->regmap,MADERA_SOFTWARE_RESET ,0 ); +if (ret !=0 ) { +dev_err (madera->dev,"Failed to soft reset device: %d\n" , ret); +return ret; + } + +/* Allow time for internal clocks to startup after reset */ +usleep_range (1000 ,2000 ); +drivers/mfd/madera-core.c line 192
Quoted 10 lines
drivers/mfd/madera-core.c new file +10
-0+return 0 ; +} + +static void madera_enable_hard_reset (struct madera *madera) +{ +if (!madera->pdata.reset) +return ; + +/* +* there are many existing out-of-tree users of these codecs that we Nit: There
Quoted 87 lines
drivers/mfd/madera-core.c new file +87
-0+* can't break so preserve the expected behaviour of setting the line +* low to assert reset +*/ +gpiod_set_raw_value_cansleep (madera->pdata.reset,0 ); +} + +static void madera_disable_hard_reset (struct madera *madera) +{ +if (!madera->pdata.reset) +return ; + +gpiod_set_raw_value_cansleep (madera->pdata.reset,1 ); +usleep_range (1000 ,2000 ); +} + +static int __maybe_unused madera_runtime_resume (struct device *dev) +{ +struct madera *madera =dev_get_drvdata (dev); +int ret; + +dev_dbg (dev,"Leaving sleep mode\n" ); + + ret =regulator_enable (madera->dcvdd); +if (ret) { +dev_err (dev,"Failed to enable DCVDD: %d\n" , ret); +return ret; + } + +regcache_cache_only (madera->regmap, false); +regcache_cache_only (madera->regmap_32bit, false); + + ret =madera_wait_for_boot (madera); +if (ret) + goto err; + + ret =regcache_sync (madera->regmap); +if (ret) { +dev_err (dev,"Failed to restore 16-bit register cache\n" ); + goto err; + } + + ret =regcache_sync (madera->regmap_32bit); +if (ret) { +dev_err (dev,"Failed to restore 32-bit register cache\n" ); + goto err; + } + +return 0 ; + +err: +regcache_cache_only (madera->regmap_32bit, true); +regcache_cache_only (madera->regmap, true); +regulator_disable (madera->dcvdd); + +return ret; +} + +static int __maybe_unused madera_runtime_suspend (struct device *dev) +{ +struct madera *madera =dev_get_drvdata (dev); + +dev_dbg (madera->dev,"Entering sleep mode\n" ); + +regcache_cache_only (madera->regmap, true); +regcache_mark_dirty (madera->regmap); +regcache_cache_only (madera->regmap_32bit, true); +regcache_mark_dirty (madera->regmap_32bit); + +regulator_disable (madera->dcvdd); + +return 0 ; +} + +const struct dev_pm_ops madera_pm_ops = { +SET_RUNTIME_PM_OPS (madera_runtime_suspend, + madera_runtime_resume, +NULL ) +}; +EXPORT_SYMBOL_GPL (madera_pm_ops); + +const struct of_device_id madera_of_match[] = { + { .compatible ="cirrus,cs47l35" , .data = (void *)CS47L35 }, + { .compatible ="cirrus,cs47l85" , .data = (void *)CS47L85 }, + { .compatible ="cirrus,cs47l90" , .data = (void *)CS47L90 }, + { .compatible ="cirrus,cs47l91" , .data = (void *)CS47L91 }, + { .compatible ="cirrus,wm1840" , .data = (void *)WM1840 }, + {}drivers/mfd/madera-core.c line 289
Quoted 10 lines
drivers/mfd/madera-core.c new file +10
-0+}; +EXPORT_SYMBOL_GPL (madera_of_match); + +static int madera_get_reset_gpio (struct madera *madera) +{ +struct gpio_desc *reset; +int ret; + + reset =devm_gpiod_get_optional (madera->dev,"reset" ,GPIOD_OUT_LOW ); +Nit: Remove this line.
drivers/mfd/madera-core.c line 292
Quoted 3 lines
drivers/mfd/madera-core.c new file +3
-0+if (IS_ERR (reset)) { + ret =PTR_ERR (reset); +if (ret == -EPROBE_DEFER )Reverse the logic and only print the error if !-EPROBE_DEFER, then you only need one return.
Quoted 5 lines
drivers/mfd/madera-core.c new file +5
-0+return ret; + +dev_err (madera->dev,"Failed to request /RESET: %d\n" , ret); +return ret; + }drivers/mfd/madera-core.c line 307
Quoted 10 lines
drivers/mfd/madera-core.c new file +10
-0+ + madera->pdata.reset = reset; + +return 0 ; +} + +static void madera_set_micbias_info (struct madera *madera) +{ +/* +* childbias is an array because future codecs can have different You mean
num_childbias?
Quoted 14 lines
drivers/mfd/madera-core.c line 318
Quoted 11 lines
drivers/mfd/madera-core.c new file +11
-0+* childbiases for each micbias +*/ +switch (madera->type) { +case CS47L35 : + madera->num_micbias =2 ; + madera->num_childbias[0 ] =2 ; + madera->num_childbias[1 ] =2 ; +return ; +case CS47L85 : +case WM1840 : + madera->num_micbias =4 ;Where are the num_childbias[x] initialised for this device?
The data struct in kzalloc in probe so we don't need to waste lines initializing zeros.
Quoted 32 lines
Quoted 19 lines
drivers/mfd/madera-core.c new file +19
-0+return ; +case CS47L90 : +case CS47L91 : + madera->num_micbias =2 ; + madera->num_childbias[0 ] =4 ; + madera->num_childbias[1 ] =4 ; +return ; +default : +return ; + } +} + +int madera_dev_init (struct madera *madera) +{ +struct device *dev = madera->dev; +unsigned int hwid; +int (*patch_fn)(struct madera *) =NULL ; +const struct mfd_cell *mfd_devs; +int n_devs =0 ;drivers/mfd/madera-core.c line 347
Quoted 10 lines
drivers/mfd/madera-core.c new file +10
-0+int i, ret; + +dev_set_drvdata (madera->dev, madera); +BLOCKING_INIT_NOTIFIER_HEAD (&madera->notifier); +madera_set_micbias_info (madera); + +if (dev_get_platdata (madera->dev)) { +memcpy (&madera->pdata,dev_get_platdata (madera->dev), +sizeof (madera->pdata)); + }Hmm... not sure about this.
Quoted 2 lines
Normally we extract what we need from pdata and place it into your ddata.
We need all our pdata and we want to share modifiable settings with the children.
Or do you mean that there's already code in the driver core that takes a copy of the pdata?
Quoted 29 lines
drivers/mfd/madera-core.c line 356
Quoted 8 lines
drivers/mfd/madera-core.c new file +8
-0+if (!madera->pdata.reset) { + ret =madera_get_reset_gpio (madera); +if (ret) +return ret; + } +if (!madera->pdata.reset) +dev_warn (madera->dev, +"Running without reset GPIO is not recommended\n" );Is this even possible? If so, handle it in
madera_get_reset_gpio().Quoted 18 lines
drivers/mfd/madera-core.c new file +18
-0+regcache_cache_only (madera->regmap, true); +regcache_cache_only (madera->regmap_32bit, true); + +for (i =0 ; i <ARRAY_SIZE (madera_core_supplies); i++) + madera->core_supplies[i].supply = madera_core_supplies[i]; + + madera->num_core_supplies =ARRAY_SIZE (madera_core_supplies); + +/* +* On some codecs DCVDD could be supplied by the internal LDO1. +* For those we must add the LDO1 driver before requesting DCVDD +* No devm_ because we need to control shutdown order of children. +*/ +switch (madera->type) { +case CS47L35 : +case CS47L90 : +case CS47L91 : +break ;
Quoted 9 lines
drivers/mfd/madera-core.c line 381
Quoted 6 lines
drivers/mfd/madera-core.c new file +6
-0+case CS47L85 : +case WM1840 : + ret =mfd_add_devices (madera->dev,PLATFORM_DEVID_NONE , + madera_ldo1_devs, +ARRAY_SIZE (madera_ldo1_devs), +NULL ,0 ,NULL );LEE: Is there any guarantee?
Of what?
Quoted 7 lines
#########################################################
#########################################################
#########################################################
#########################################################
#########################################################
#########################################################
??
Quoted 18 lines
Quoted 18 lines
drivers/mfd/madera-core.c new file +18
-0+if (ret) { +dev_err (dev,"Failed to add LDO1 child: %d\n" , ret); +return ret; + } +break ; +default : +/* No point continuing if the type is unknown */ +dev_err (madera->dev,"Unknown device type %d\n" , madera->type); +return -ENODEV ; + } + + ret =devm_regulator_bulk_get (dev, madera->num_core_supplies, + madera->core_supplies); +if (ret) { +dev_err (dev,"Failed to request core supplies: %d\n" , ret); + goto err_devs; + } +
Quoted 9 lines
drivers/mfd/madera-core.c line 405
Quoted 6 lines
drivers/mfd/madera-core.c new file +6
-0+/* +* Don't use devres here because the only device we have to get +* against is the MFD device and DCVDD will likely be supplied by +* one of its children. Meaning that the regulator will be +* destroyed by the time devres calls regulator put. +*/ I'm confused. So the regulator you're *_get()ing doesn't exist yet?
No, it's what it says in the comment. If the regulator is a child of this mfd it will be removed before the parent mfd is removed so when the devm tries to put() it has already gone - BANG.
Quoted 31 lines
Quoted 18 lines
drivers/mfd/madera-core.c new file +18
-0+ madera->dcvdd =regulator_get (madera->dev,"DCVDD" ); +if (IS_ERR (madera->dcvdd)) { + ret =PTR_ERR (madera->dcvdd); +dev_err (dev,"Failed to request DCVDD: %d\n" , ret); + goto err_devs; + } + + ret =regulator_bulk_enable (madera->num_core_supplies, + madera->core_supplies); +if (ret) { +dev_err (dev,"Failed to enable core supplies: %d\n" , ret); + goto err_dcvdd; + } + + ret =regulator_enable (madera->dcvdd); +if (ret) { +dev_err (dev,"Failed to enable DCVDD: %d\n" , ret); + goto err_enable;drivers/mfd/madera-core.c line 433
Quoted 10 lines
drivers/mfd/madera-core.c new file +10
-0+ } + +madera_disable_hard_reset (madera); + +regcache_cache_only (madera->regmap, false); +regcache_cache_only (madera->regmap_32bit, false); + +/* +* Verify that this is a chip we know about before we +* starting doing any writes to its registers Nit: start
Quoted 2 lines
Shouldn't you do this *before* you start to set everything up above?
No. You can't read registers until you have applied power and taken the chip out of hard reset.
Quoted 5 lines
drivers/mfd/madera-core.c line 433
Quoted 2 lines
drivers/mfd/madera-core.c new file +2
-0+*/ + ret =regmap_read (madera->regmap,MADERA_SOFTWARE_RESET , &hwid);
MADERA_SOFTWARE_RESET?
That's what the register is called. It's in the datasheet.
Quoted 14 lines
drivers/mfd/madera-core.c line 446
Quoted 11 lines
drivers/mfd/madera-core.c new file +11
-0+if (ret) { +dev_err (dev,"Failed to read ID register: %d\n" , ret); + goto err_reset; + } + +switch (hwid) { +case CS47L35_SILICON_ID : +if (IS_ENABLED (CONFIG_MFD_CS47L35 )) { +switch (madera->type) { +case CS47L35 : + patch_fn = cs47l35_patch;I've always hated these.
Quoted 3 lines
Why doesn't the device come with a sensible default configuration that you can sensibly adjust accordingly in a *sane* way?
Google "post-silicon tuning" or see
https://en.wikipedia.org/wiki/Integrated_circuit_design#Analog_design
and
https://tinyurl.com/y8qxa599
Analog is affected by process variation. If you don't care about the performance you can leave it at some defaults but our customers expect high-quality audio so we want to tune for the best performance. The tuning isn't some controls you can give to the user to "play with until it sounds right". It takes skilled engineers with knowledge of the insides of the chip to come up with tunings and a coherent set of values.
Quoted 48 lines
Quoted 48 lines
drivers/mfd/madera-core.c new file +48
-0+ mfd_devs = cs47l35_devs; + n_devs =ARRAY_SIZE (cs47l35_devs); +break ; +default : +break ; + } + } +break ; +case CS47L85_SILICON_ID : +if (IS_ENABLED (CONFIG_MFD_CS47L85 )) { +switch (madera->type) { +case CS47L85 : +case WM1840 : + patch_fn = cs47l85_patch; + mfd_devs = cs47l85_devs; + n_devs =ARRAY_SIZE (cs47l85_devs); +break ; +default : +break ; + } + } +break ; +case CS47L90_SILICON_ID : +if (IS_ENABLED (CONFIG_MFD_CS47L90 )) { +switch (madera->type) { +case CS47L90 : +case CS47L91 : + patch_fn = cs47l90_patch; + mfd_devs = cs47l90_devs; + n_devs =ARRAY_SIZE (cs47l90_devs); +break ; +default : +break ; + } + } +break ; +default : +dev_err (madera->dev,"Unknown device ID: %x\n" , hwid); + ret = -EINVAL ; + goto err_reset; + } + +if (!n_devs) { +dev_err (madera->dev,"Device ID 0x%x not a %s\n" , hwid, + madera->type_name); + ret = -ENODEV ; + goto err_reset; + }
Quoted 9 lines
drivers/mfd/madera-core.c line 500
Quoted 6 lines
drivers/mfd/madera-core.c new file +6
-0+ +/* +* It looks like a device we support. If we don't have a hard reset +* we can now attempt a soft reset +*/ +if (!madera->pdata.reset) {Call the reset regardless and do any affiliated checks *inside*.
No. We don't want to be doing spurious unnecessary resets. We _only_ call soft reset if we didn't have a GPIO to be able to do a full hard reset. We can't combine hard and soft into one function, the sequencing is different. Hard reset is asserted before powering the chip up. Soft reset is a command so can only be issued after the chip is powered up. You can see from the code that we call hard reset control in different places to the soft reset.
Quoted 173 lines
Quoted 173 lines
drivers/mfd/madera-core.c new file +100
-0+ ret =madera_soft_reset (madera); +if (ret) + goto err_reset; + } + + ret =madera_wait_for_boot (madera); +if (ret) { +dev_err (madera->dev,"Device failed initial boot: %d\n" , ret); + goto err_reset; + } + + ret =regmap_read (madera->regmap,MADERA_HARDWARE_REVISION , + &madera->rev); +if (ret) { +dev_err (dev,"Failed to read revision register: %d\n" , ret); + goto err_reset; + } + madera->rev &=MADERA_HW_REVISION_MASK ; + +dev_info (dev,"%s silicon revision %d\n" , madera->type_name, + madera->rev); + +/* Apply hardware patch */ +if (patch_fn) { + ret =patch_fn (madera); +if (ret) { +dev_err (madera->dev,"Failed to apply patch %d\n" , ret); + goto err_reset; + } + } + +/* Init 32k clock sourced from MCLK2 */ + ret =regmap_update_bits (madera->regmap, +MADERA_CLOCK_32K_1 , +MADERA_CLK_32K_ENA_MASK |MADERA_CLK_32K_SRC_MASK , +MADERA_CLK_32K_ENA |MADERA_32KZ_MCLK2 ); +if (ret) { +dev_err (madera->dev,"Failed to init 32k clock: %d\n" , ret); + goto err_reset; + } + +pm_runtime_set_active (madera->dev); +pm_runtime_enable (madera->dev); +pm_runtime_set_autosuspend_delay (madera->dev,100 ); +pm_runtime_use_autosuspend (madera->dev); + +/* No devm_ because we need to control shutdown order of children */ + ret =mfd_add_devices (madera->dev,PLATFORM_DEVID_NONE , + mfd_devs, n_devs, +NULL ,0 ,NULL ); +if (ret) { +dev_err (madera->dev,"Failed to add subdevices: %d\n" , ret); + goto err_pm_runtime; + } + +return 0 ; + +err_pm_runtime: +pm_runtime_disable (madera->dev); +err_reset: +madera_enable_hard_reset (madera); +regulator_disable (madera->dcvdd); +err_enable: +regulator_bulk_disable (madera->num_core_supplies, + madera->core_supplies); +err_dcvdd: +regulator_put (madera->dcvdd); +err_devs: +mfd_remove_devices (dev); + +return ret; +} +EXPORT_SYMBOL_GPL (madera_dev_init); + +int madera_dev_exit (struct madera *madera) +{ +/* Prevent any IRQs being serviced while we clean up */ +disable_irq (madera->irq); + +/* +* DCVDD could be supplied by a child node, we must disable it before +* removing the children, and prevent PM runtime from turning it back on +*/ +pm_runtime_disable (madera->dev); + +regulator_disable (madera->dcvdd); +regulator_put (madera->dcvdd); + +mfd_remove_devices (madera->dev); +madera_enable_hard_reset (madera); + +regulator_bulk_disable (madera->num_core_supplies, + madera->core_supplies); +return 0 ; +} +EXPORT_SYMBOL_GPL (madera_dev_exit); + +MODULE_DESCRIPTION ("Madera core MFD driver" ); +MODULE_AUTHOR ("Richard Fitzgerald <[email protected]>" ); +MODULE_LICENSE ("GPL v2" );drivers/mfd/madera-i2c.c new file +67
-0@@ -0,0 +1,139 @@ +// 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 ; + } +
Quoted 9 lines
drivers/mfd/madera-i2c.c line 72
Quoted 5 lines
drivers/mfd/madera-i2c.c new file +5
-0+ name =madera_name_from_type (type); + +if (!regmap_16bit_config) { +dev_err (&i2c->dev, +"Kernel does not include support for %s\n" , name);So you have provided support for devices in
madera_name_from_type(), but not elsewhere?
I'm sorry. I don't understand. Surely if the kernel has been compiled without support for a chip it's useful to be able to log a meaningful string to help with a menuconfig if there's an attempt to use that chip?
Quoted 139 lines
Quoted 139 lines
drivers/mfd/madera-i2c.c new file +67
-0+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 <[email protected]>" ); +MODULE_LICENSE ("GPL v2" );drivers/mfd/madera-spi.c new file +66
-0@@ -0,0 +1,138 @@ +// 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 ; + }
Quoted 9 lines
drivers/mfd/madera-spi.c line 72
Quoted 6 lines
drivers/mfd/madera-spi.c new file +6
-0+ + name =madera_name_from_type (type); + +if (!regmap_16bit_config) { +dev_err (&spi->dev, +"Kernel does not include support for %s\n" , name);As above?
As above.
Quoted 370 lines
Quoted 370 lines
drivers/mfd/madera-spi.c new file +66
-0+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 <[email protected]>" ); +MODULE_LICENSE ("GPL v2" );drivers/mfd/madera.h new file +44
-0@@ -0,0 +1,44 @@ +/* +* 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 include/linux/mfd/madera/core.h new file +187
-0@@ -0,0 +1,187 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* MFD internals 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. +*/ + +#ifndef MADERA_CORE_H +#define MADERA_CORE_H + +#include <linux/gpio/consumer.h> +#include <linux/interrupt.h> +#include <linux/mfd/madera/pdata.h> +#include <linux/notifier.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> + +enum madera_type { +/* 0 is reserved for indicating failure to identify */ +CS47L35 =1 , +CS47L85 =2 , +CS47L90 =3 , +CS47L91 =4 , +WM1840 =7 , +}; + +#define MADERA_MAX_CORE_SUPPLIES 2 +#define MADERA_MAX_GPIOS 40 + +#define CS47L35_NUM_GPIOS 16 +#define CS47L85_NUM_GPIOS 40 +#define CS47L90_NUM_GPIOS 38 + +#define MADERA_MAX_MICBIAS 4 + +/* Notifier events */ +#define MADERA_NOTIFY_VOICE_TRIGGER 0x1 +#define MADERA_NOTIFY_HPDET 0x2 +#define MADERA_NOTIFY_MICDET 0x4 + +/* GPIO Function Definitions */ +#define MADERA_GP_FN_ALTERNATE 0x00 +#define MADERA_GP_FN_GPIO 0x01 +#define MADERA_GP_FN_DSP_GPIO 0x02 +#define MADERA_GP_FN_IRQ1 0x03 +#define MADERA_GP_FN_IRQ2 0x04 +#define MADERA_GP_FN_FLL1_CLOCK 0x10 +#define MADERA_GP_FN_FLL2_CLOCK 0x11 +#define MADERA_GP_FN_FLL3_CLOCK 0x12 +#define MADERA_GP_FN_FLLAO_CLOCK 0x13 +#define MADERA_GP_FN_FLL1_LOCK 0x18 +#define MADERA_GP_FN_FLL2_LOCK 0x19 +#define MADERA_GP_FN_FLL3_LOCK 0x1A +#define MADERA_GP_FN_FLLAO_LOCK 0x1B +#define MADERA_GP_FN_OPCLK_OUT 0x40 +#define MADERA_GP_FN_OPCLK_ASYNC_OUT 0x41 +#define MADERA_GP_FN_PWM1 0x48 +#define MADERA_GP_FN_PWM2 0x49 +#define MADERA_GP_FN_SPDIF_OUT 0x4C +#define MADERA_GP_FN_HEADPHONE_DET 0x50 +#define MADERA_GP_FN_MIC_DET 0x58 +#define MADERA_GP_FN_DRC1_SIGNAL_DETECT 0x80 +#define MADERA_GP_FN_DRC2_SIGNAL_DETECT 0x81 +#define MADERA_GP_FN_ASRC1_IN1_LOCK 0x88 +#define MADERA_GP_FN_ASRC1_IN2_LOCK 0x89 +#define MADERA_GP_FN_ASRC2_IN1_LOCK 0x8A +#define MADERA_GP_FN_ASRC2_IN2_LOCK 0x8B +#define MADERA_GP_FN_DSP_IRQ1 0xA0 +#define MADERA_GP_FN_DSP_IRQ2 0xA1 +#define MADERA_GP_FN_DSP_IRQ3 0xA2 +#define MADERA_GP_FN_DSP_IRQ4 0xA3 +#define MADERA_GP_FN_DSP_IRQ5 0xA4 +#define MADERA_GP_FN_DSP_IRQ6 0xA5 +#define MADERA_GP_FN_DSP_IRQ7 0xA6 +#define MADERA_GP_FN_DSP_IRQ8 0xA7 +#define MADERA_GP_FN_DSP_IRQ9 0xA8 +#define MADERA_GP_FN_DSP_IRQ10 0xA9 +#define MADERA_GP_FN_DSP_IRQ11 0xAA +#define MADERA_GP_FN_DSP_IRQ12 0xAB +#define MADERA_GP_FN_DSP_IRQ13 0xAC +#define MADERA_GP_FN_DSP_IRQ14 0xAD +#define MADERA_GP_FN_DSP_IRQ15 0xAE +#define MADERA_GP_FN_DSP_IRQ16 0xAF +#define MADERA_GP_FN_HPOUT1L_SC 0xB0 +#define MADERA_GP_FN_HPOUT1R_SC 0xB1 +#define MADERA_GP_FN_HPOUT2L_SC 0xB2 +#define MADERA_GP_FN_HPOUT2R_SC 0xB3 +#define MADERA_GP_FN_HPOUT3L_SC 0xB4 +#define MADERA_GP_FN_HPOUT4R_SC 0xB5 +#define MADERA_GP_FN_SPKOUTL_SC 0xB6 +#define MADERA_GP_FN_SPKOUTR_SC 0xB7 +#define MADERA_GP_FN_HPOUT1L_ENA 0xC0 +#define MADERA_GP_FN_HPOUT1R_ENA 0xC1 +#define MADERA_GP_FN_HPOUT2L_ENA 0xC2 +#define MADERA_GP_FN_HPOUT2R_ENA 0xC3 +#define MADERA_GP_FN_HPOUT3L_ENA 0xC4 +#define MADERA_GP_FN_HPOUT4R_ENA 0xC5 +#define MADERA_GP_FN_SPKOUTL_ENA 0xC6 +#define MADERA_GP_FN_SPKOUTR_ENA 0xC7 +#define MADERA_GP_FN_HPOUT1L_DIS 0xD0 +#define MADERA_GP_FN_HPOUT1R_DIS 0xD1 +#define MADERA_GP_FN_HPOUT2L_DIS 0xD2 +#define MADERA_GP_FN_HPOUT2R_DIS 0xD3 +#define MADERA_GP_FN_HPOUT3L_DIS 0xD4 +#define MADERA_GP_FN_HPOUT4R_DIS 0xD5 +#define MADERA_GP_FN_SPKOUTL_DIS 0xD6 +#define MADERA_GP_FN_SPKOUTR_DIS 0xD7 +#define MADERA_GP_FN_SPK_SHUTDOWN 0xE0 +#define MADERA_GP_FN_SPK_OVH_SHUTDOWN 0xE1 +#define MADERA_GP_FN_SPK_OVH_WARN 0xE2 +#define MADERA_GP_FN_TIMER1_STATUS 0x140 +#define MADERA_GP_FN_TIMER2_STATUS 0x141 +#define MADERA_GP_FN_TIMER3_STATUS 0x142 +#define MADERA_GP_FN_TIMER4_STATUS 0x143 +#define MADERA_GP_FN_TIMER5_STATUS 0x144 +#define MADERA_GP_FN_TIMER6_STATUS 0x145 +#define MADERA_GP_FN_TIMER7_STATUS 0x146 +#define MADERA_GP_FN_TIMER8_STATUS 0x147 +#define MADERA_GP_FN_EVENTLOG1_FIFO_STS 0x150 +#define MADERA_GP_FN_EVENTLOG2_FIFO_STS 0x151 +#define MADERA_GP_FN_EVENTLOG3_FIFO_STS 0x152 +#define MADERA_GP_FN_EVENTLOG4_FIFO_STS 0x153 +#define MADERA_GP_FN_EVENTLOG5_FIFO_STS 0x154 +#define MADERA_GP_FN_EVENTLOG6_FIFO_STS 0x155 +#define MADERA_GP_FN_EVENTLOG7_FIFO_STS 0x156 +#define MADERA_GP_FN_EVENTLOG8_FIFO_STS 0x157 + +struct snd_soc_dapm_context ; + +/* +* struct madera - internal data shared by the set of Madera drivers +* +* This should not be used by anything except child drivers of the Madera MFD +* +* @regmap: pointer to the regmap instance for 16-bit registers +* @regmap_32bit: pointer to the regmap instance for 32-bit registers +* @dev: pointer to the MFD device +* @type: type of codec +* @rev: silicon revision +* @type_name: display name of this codec +* @num_core_supplies: number of core supply regulators +* @core_supplies: list of core supplies that are always required +* @dcvdd: pointer to DCVDD regulator +* @internal_dcvdd: true if DCVDD is supplied from the internal LDO1 +* @pdata: our pdata +* @irq_dev: the irqchip child driver device +* @irq: host irq number from SPI or I2C configuration +* @out_clamp: indicates output clamp 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 +* @num_micbias: number of MICBIAS outputs +* @num_childbias: number of child biases for each MICBIAS +* @dapm: pointer to codec driver DAPM context +* @notifier: notifier for signalling events to ASoC machine driver +*/ +struct madera { +struct regmap *regmap; +struct regmap *regmap_32bit; + +struct device *dev; + +enum madera_type type; +unsigned int rev; +const char *type_name; + +int num_core_supplies; +struct regulator_bulk_data core_supplies[MADERA_MAX_CORE_SUPPLIES ]; +struct regulator *dcvdd; +bool internal_dcvdd; + +struct madera_pdata pdata; + +struct device *irq_dev; +int irq; + +unsigned int num_micbias; +unsigned int num_childbias[MADERA_MAX_MICBIAS ]; + +struct snd_soc_dapm_context *dapm; + +struct blocking_notifier_head notifier; +}; +#endif include/linux/mfd/madera/pdata.h new file +55
-0@@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Platform data 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. +*/ + +#ifndef MADERA_PDATA_H +#define MADERA_PDATA_H + +#include <linux/kernel.h> +#include <linux/regulator/arizona-ldo1.h> +#include <linux/regulator/arizona-micsupp.h> +#include <linux/regulator/machine.h> + +#define MADERA_MAX_MICBIAS 4 +#define MADERA_MAX_CHILD_MICBIAS 4 + +#define MADERA_MAX_GPSW 2 + +struct gpio_desc; +struct pinctrl_map; +struct madera_irqchip_pdata; +struct madera_codec_pdata; + +/** + * struct madera_pdata - Configuration data for Madera devices + * + * @reset: GPIO controlling /RESET (NULL = none) + * @ldo1: Substruct of pdata for the LDO1 regulator + * @micvdd: Substruct of pdata for the MICVDD regulator + * @irqchip: Pointer to optional pdata for the irqchip driver + * @gpio_base: Base GPIO number + * @gpio_configs: Array of GPIO configurations (See Documentation/pinctrl.txt) + * @n_gpio_configs: Number of entries in gpio_configs + * @codec: Pointer to optional pdata for the ASoC codec driver + * See include/sound/madera-pdata.h + * @gpsw: General purpose switch mode setting (See the SW1_MODE field + * in the datasheet for the available values for your codec) + */ +struct madera_pdata { + struct gpio_desc *reset; + + struct arizona_ldo1_pdata ldo1; + struct arizona_micsupp_pdata micvdd; + + struct madera_irqchip_pdata *irqchip; + + int gpio_base; + + const struct pinctrl_map *gpio_configs;
Quoted 9 lines
include/linux/mfd/madera/pdata.h line 61
Quoted 6 lines
include/linux/mfd/madera/pdata.h new file +6
-0+int n_gpio_configs; + +struct madera_codec_pdata *codec; + +u32 gpsw[MADERA_MAX_GPSW ]; +};This doesn't look like platform data. Where does it come from?
In what way doesn't it look like platform data?
A bunch of information about external hardware that we wouldn't be able to guess sounds like pdata to me.
Quoted 2 lines
Quoted 1 line
include/linux/mfd/madera/pdata.h new file +1
-0+#endif
Richard Fitzgerald
maintainerPATCH v9 4/9 mfd: madera: Register map tables for Cirrus Logic CS47L35
In reply to Richard FitzgeraldRegmap configuration tables for Cirrus Logic CS47L35 codecs.
--- drivers/mfd/Kconfig | 7 + drivers/mfd/Makefile | 3 + drivers/mfd/cs47l35-tables.c | 1609 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1619 insertions(+) create mode 100644 drivers/mfd/cs47l35-tables.c
drivers/mfd/Kconfig +7 -0
@@ -261,6 +261,13 @@ config MFD_MADERA_SPI 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_ASIC3 bool "Compaq ASIC3" depends on GPIOLIB && ARM
drivers/mfd/Makefile +3 -0
@@ -73,6 +73,9 @@ obj-$(CONFIG_MFD_WM8994) += wm8994.o obj-$(CONFIG_MFD_WM97xx) += wm97xx-core.o madera-objs := madera-core.o +ifeq ($(CONFIG_MFD_CS47L35),y) +madera-objs += cs47l35-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
drivers/mfd/cs47l35-tables.c new file +1609 -0
1,609 lines not on this page · raw message
Signature · 1 line
2.11.0
Richard Fitzgerald
maintainerPATCH v9 5/9 mfd: madera: Register map tables for Cirrus Logic CS47L85
In reply to Richard FitzgeraldRegmap configuration tables for Cirrus Logic CS47L85 codecs.
--- drivers/mfd/Kconfig | 7 + drivers/mfd/Makefile | 3 + drivers/mfd/cs47l85-tables.c | 3009 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 3019 insertions(+) create mode 100644 drivers/mfd/cs47l85-tables.c
drivers/mfd/Kconfig +7 -0
@@ -268,6 +268,13 @@ config MFD_CS47L35 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_ASIC3 bool "Compaq ASIC3" depends on GPIOLIB && ARM
drivers/mfd/Makefile +3 -0
@@ -76,6 +76,9 @@ 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 obj-$(CONFIG_MFD_MADERA) += madera.o obj-$(CONFIG_MFD_MADERA_I2C) += madera-i2c.o obj-$(CONFIG_MFD_MADERA_SPI) += madera-spi.o
drivers/mfd/cs47l85-tables.c new file +3009 -0
2,978 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Signature · 1 line
2.11.0
Part of the diff is not shown here. View the raw message.
Richard Fitzgerald
maintainerPATCH v9 6/9 mfd: madera: Register map tables for Cirrus Logic CS47L90/91
In reply to Richard FitzgeraldRegmap configuration tables for Cirrus Logic CS47L90 and CS47L91 codecs.
--- drivers/mfd/Kconfig | 7 + drivers/mfd/Makefile | 3 + drivers/mfd/cs47l90-tables.c | 2674 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 2684 insertions(+) create mode 100644 drivers/mfd/cs47l90-tables.c
drivers/mfd/Kconfig +7 -0
@@ -275,6 +275,13 @@ config MFD_CS47L85 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 bool "Compaq ASIC3" depends on GPIOLIB && ARM
drivers/mfd/Makefile +3 -0
@@ -79,6 +79,9 @@ 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
drivers/mfd/cs47l90-tables.c new file +2674 -0
2,674 lines not on this page · raw message
Signature · 1 line
2.11.0
Richard Fitzgerald
maintainerPATCH v9 7/9 pinctrl: madera: Add DT bindings for Cirrus Logic Madera codecs
In reply to Richard FitzgeraldThis is the binding description of the pinctrl driver for Cirrus Logic Madera codecs. The binding uses the generic pinctrl binding so the main purpose here is to describe the device-specific names for groups and functions.
--- .../bindings/pinctrl/cirrus,madera-pinctrl.txt | 99 ++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 Documentation/devicetree/bindings/pinctrl/cirrus,madera-pinctrl.txt
Documentation/devicetree/bindings/pinctrl/cirrus,madera-pinctrl.txt new file +99 -0
@@ -0,0 +1,99 @@ +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>; + }; + }; +};
Signature · 1 line
2.11.0
Re: [PATCH v9 7/9] pinctrl: madera: Add DT bindings for Cirrus Logic Madera codecs
Quoted 7 lines · Richard Fitzgerald
This is the binding description of the pinctrl driver for Cirrus Logic Madera codecs. The binding uses the generic pinctrl binding so the main purpose here is to describe the device-specific names for groups and functions.
Signed-off-by Richard Fitzgerald <[email protected]>Acked-by Rob Herring <[email protected]>
I can also just apply this if you want, as it has no dependencies to anything else. I just assume you want to keep it together with the rest of this complex series.
Yours,
Linus Walleij
Richard Fitzgerald
maintainerRe: [PATCH v9 7/9] pinctrl: madera: Add DT bindings for Cirrus Logic Madera codecs
Quoted 8 lines · Linus Walleij
Quoted 5 lines · Richard Fitzgerald
This is the binding description of the pinctrl driver for Cirrus Logic Madera codecs. The binding uses the generic pinctrl binding so the main purpose here is to describe the device-specific names for groups and functions.
Quoted 6 lines
Quoted 2 lines
Signed-off-by Richard Fitzgerald <[email protected]>Acked-by Rob Herring <[email protected]>Acked-by Linus Walleij <[email protected]>I can also just apply this if you want, as it has no dependencies to
No let's leave it. There's no point the kernel source containing a binding description for drivers that don't exist and I've no idea how long it might take for the drivers to actually get into the kernel. We've been going about a year now with these patches...
Quoted 6 lines
anything else. I just assume you want to keep it together with the rest of this complex series.
Yours,
Linus Walleij
Richard Fitzgerald
maintainerRe: [PATCH v9 7/9] pinctrl: madera: Add DT bindings for Cirrus Logic Madera codecs
In reply to Linus WalleijQuoted 11 lines · Linus Walleij
Quoted 7 lines · Richard Fitzgerald
This is the binding description of the pinctrl driver for Cirrus Logic Madera codecs. The binding uses the generic pinctrl binding so the main purpose here is to describe the device-specific names for groups and functions.
Signed-off-by Richard Fitzgerald <[email protected]>Acked-by Rob Herring <[email protected]>
Quoted 9 lines
Acked-by Linus Walleij <[email protected]>I can also just apply this if you want, as it has no dependencies to anything else. I just assume you want to keep it together with the rest of this complex series.
Yours,
Linus Walleij
Linus,
What is your opinion of the i.MX6 pinctrl failure after my bugfix patch for the hogs?
If you would want to revert my patch I would need to change this pinctrl driver so it has its own child node as a workaround to the hog bug.
Or do you think it is more likely a bug in the i.MX6 pinctrl driver?
Re: [PATCH v9 7/9] pinctrl: madera: Add DT bindings for Cirrus Logic Madera codecs
Quoted 2 lines · Richard Fitzgerald
What is your opinion of the i.MX6 pinctrl failure after my bugfix patch for the hogs?
Don't know yet. I will answer to that patch, when I get to it.
Quoted 4 lines
If you would want to revert my patch I would need to change this pinctrl driver so it has its own child node as a workaround to the hog bug.
Or do you think it is more likely a bug in the i.MX6 pinctrl driver?
No idea yet. I bet you folks have battled it out and know it better than me already.
Yours,
Linus Walleij
Richard Fitzgerald
maintainerPATCH v9 8/9 pinctrl: madera: Add driver for Cirrus Logic Madera codecs
In reply to Richard FitzgeraldThese codecs have a variable number of I/O lines each of which is individually selectable to a wide range of possible functions.
The functionality is slightly different from the traditional muxed GPIO since most of the functions can be mapped to any pin (and even the same function to multiple pins). Most pins have a dedicated "alternate" function that is only available on that pin. The alternate functions are usually a group of signals, though it is not always necessary to enable the full group, depending on the alternate function and how it is to be used. The mapping between alternate functions and GPIO pins varies between codecs depending on the number of alternate functions and available pins.
---
There are some minor changes since LinusW last reviewed this patch but as they are trivial I have carried forward Linus's Reviewed-by:
- SPDX license headers
- can now build it as a module
- avoided a minor checkpatch warning about an unnecessary else {} in madera_get_group_name()
--- MAINTAINERS | 2 + drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/cirrus/Kconfig | 15 + drivers/pinctrl/cirrus/Makefile | 13 + drivers/pinctrl/cirrus/pinctrl-cs47l35.c | 45 ++ drivers/pinctrl/cirrus/pinctrl-cs47l85.c | 59 ++ drivers/pinctrl/cirrus/pinctrl-cs47l90.c | 57 ++ drivers/pinctrl/cirrus/pinctrl-madera-core.c | 1074 ++++++++++++++++++++++++++ drivers/pinctrl/cirrus/pinctrl-madera.h | 41 + 10 files changed, 1308 insertions(+) create mode 100644 drivers/pinctrl/cirrus/Kconfig create mode 100644 drivers/pinctrl/cirrus/Makefile create mode 100644 drivers/pinctrl/cirrus/pinctrl-cs47l35.c create mode 100644 drivers/pinctrl/cirrus/pinctrl-cs47l85.c create mode 100644 drivers/pinctrl/cirrus/pinctrl-cs47l90.c create mode 100644 drivers/pinctrl/cirrus/pinctrl-madera-core.c create mode 100644 drivers/pinctrl/cirrus/pinctrl-madera.h
MAINTAINERS +2 -0
@@ -3499,9 +3499,11 @@ 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/mfd/madera* F: drivers/mfd/cs47l* +F: drivers/pinctrl/cirrus/* CLEANCACHE API M: Konrad Rzeszutek Wilk <[email protected]>
drivers/pinctrl/Kconfig +1 -0
@@ -378,6 +378,7 @@ source "drivers/pinctrl/vt8500/Kconfig" source "drivers/pinctrl/mediatek/Kconfig" source "drivers/pinctrl/zte/Kconfig" source "drivers/pinctrl/meson/Kconfig" +source "drivers/pinctrl/cirrus/Kconfig" config PINCTRL_XWAY bool
drivers/pinctrl/Makefile +1 -0
@@ -66,3 +66,4 @@ obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/ obj-$(CONFIG_ARCH_VT8500) += vt8500/ obj-y += mediatek/ obj-$(CONFIG_PINCTRL_ZX) += zte/ +obj-y += cirrus/
drivers/pinctrl/cirrus/Kconfig new file +15 -0
@@ -0,0 +1,15 @@ +# This is all selected by the Madera MFD driver Kconfig options +config PINCTRL_MADERA + tristate + select PINMUX + select GENERIC_PINCONF + +config PINCTRL_CS47L35 + bool + +config PINCTRL_CS47L85 + bool + +config PINCTRL_CS47L90 + bool +
drivers/pinctrl/cirrus/Makefile new file +13 -0
@@ -0,0 +1,13 @@ +# Cirrus Logic pinctrl drivers +pinctrl-madera-objs := pinctrl-madera-core.o +ifeq ($(CONFIG_PINCTRL_CS47L35),y) +pinctrl-madera-objs += pinctrl-cs47l35.o +endif +ifeq ($(CONFIG_PINCTRL_CS47L85),y) +pinctrl-madera-objs += pinctrl-cs47l85.o +endif +ifeq ($(CONFIG_PINCTRL_CS47L90),y) +pinctrl-madera-objs += pinctrl-cs47l90.o +endif + +obj-$(CONFIG_PINCTRL_MADERA) += pinctrl-madera.o
drivers/pinctrl/cirrus/pinctrl-cs47l35.c new file +45 -0
45 lines not on this page · raw message
drivers/pinctrl/cirrus/pinctrl-cs47l85.c new file +59 -0
59 lines not on this page · raw message
drivers/pinctrl/cirrus/pinctrl-cs47l90.c new file +57 -0
57 lines not on this page · raw message
drivers/pinctrl/cirrus/pinctrl-madera-core.c new file +1074 -0
1,074 lines not on this page · raw message
drivers/pinctrl/cirrus/pinctrl-madera.h new file +41 -0
41 lines not on this page · raw message
Signature · 1 line
2.11.0
kbuild test robot
build botRe: [PATCH v9 8/9] pinctrl: madera: Add driver for Cirrus Logic Madera codecs
I love your patch! Yet something to improve:
Hi Richard,
I love your patch! Yet something to improve:
[auto build test ERROR on linus/master]
[also build test ERROR on v4.16-rc6 next-20180322]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Richard-Fitzgerald/mfd-madera-Add-register-definitions-for-Cirrus-Logic-Madera-codecs/20180314-211822
config: i386-randconfig-x010-03221515 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=i386 All errors (new ones prefixed by >>):
>> drivers/pinctrl/cirrus/pinctrl-madera-core.c:561:20: error: 'pinconf_generic_dt_node_to_map_all' undeclared here (not in a function); did you mean 'pinconf_generic_params'?
.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pinconf_generic_params
vim +561 drivers/pinctrl/cirrus/pinctrl-madera-core.c
555
556
557 static const struct pinctrl_ops madera_pin_group_ops = {
558 .get_groups_count = madera_get_groups_count,
559 .get_group_name = madera_get_group_name,
560 .get_group_pins = madera_get_group_pins,
> 561 .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
562 .dt_free_map = pinctrl_utils_free_map,
563 #if IS_ENABLED(CONFIG_DEBUG_FS)
564 .pin_dbg_show = madera_pin_dbg_show,
565 #endif
566 };
567
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Re: [PATCH v9 8/9] pinctrl: madera: Add driver for Cirrus Logic Madera codecs
Quoted 3 lines · kbuild test robot
Hi Richard,
I love your patch! Yet something to improve:
Looking to apply this set soon.
I guess this needs fixing first though?
Quoted 37 lines
[auto build test ERROR on linus/master]
[also build test ERROR on v4.16-rc6 next-20180322]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]url: https://github.com/0day-ci/linux/commits/Richard-Fitzgerald/mfd-madera-Add-register-definitions-for-Cirrus-Logic-Madera-codecs/20180314-211822
config: i386-randconfig-x010-03221515 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:# save the attached .config to linux build tree make ARCH=i386All errors (new ones prefixed by >>):
Quoted 1 line
Quoted 1 line
drivers/pinctrl/cirrus/pinctrl-madera-core.c:561:20: error: 'pinconf_generic_dt_node_to_map_all' undeclared here (not in a function); did you mean 'pinconf_generic_params'?.dt_node_to_map =
pinconf_generic_dt_node_to_map_all,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~pinconf_generic_paramsvim +561
drivers/pinctrl/cirrus/pinctrl-madera-core.c555 556 557 static const struct pinctrl_ops madera_pin_group_ops = { 558 .get_groups_count = madera_get_groups_count, 559 .get_group_name = madera_get_group_name, 560 .get_group_pins = madera_get_group_pins,Quoted 1 line
561 .dt_node_to_map =
pinconf_generic_dt_node_to_map_all,562 .dt_free_map =
pinctrl_utils_free_map,
563 #ifIS_ENABLED(CONFIG_DEBUG_FS)
564 .pin_dbg_show =madera_pin_dbg_show,
565 #endif566 }; 567---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Signature · 4 lines
Lee Jones [李琼斯] Linaro Services Technical Lead Linaro.org │ Open source software for ARM SoCs Follow Linaro: Facebook | Twitter | Blog
Richard Fitzgerald
maintainerPATCH v9 9/9 gpio: madera: Support Cirrus Logic Madera class codecs
In reply to Richard FitzgeraldThis adds support for the GPIOs on Cirrus Logic Madera class codecs. Any pins not used for special functions (see the pinctrl driver) can be used as general single-bit input or output lines. The number of available GPIOs varies between codecs.
Note that this is part of a composite MFD for these codecs and can only be used with the corresponding MFD and other child drivers on those silicon. The GPIO block on these codecs does not exist indepedently of the rest of the MFD.
---
Changes since V7:
As the changes are all small and mostly coding style, I've carried forward Linus's previous ack.
- SPDX license headers
- can now build as a module
- fixed some coding style issues raised by Andy Shevchenko and Linus Walleij
- commented why we are calling gpiochip_add_pin_range()
- commented why there is a struct gpio_chip inside struct madera_gpio
--- MAINTAINERS | 1 + drivers/gpio/Kconfig | 6 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-madera.c | 206 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 214 insertions(+) create mode 100644 drivers/gpio/gpio-madera.c
MAINTAINERS +1 -0
@@ -3501,6 +3501,7 @@ 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/*
drivers/gpio/Kconfig +6 -0
@@ -1020,6 +1020,12 @@ config GPIO_LP87565 This driver can also be built as a module. If so, the module will be 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 tristate "GPIO support for PMIC MAX77620 and MAX20024" depends on MFD_MAX77620
drivers/gpio/Makefile +1 -0
@@ -71,6 +71,7 @@ obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o obj-$(CONFIG_GPIO_LP873X) += gpio-lp873x.o obj-$(CONFIG_GPIO_LP87565) += gpio-lp87565.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_MAX730X) += gpio-max730x.o obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o
drivers/gpio/gpio-madera.c new file +206 -0
206 lines not on this page · raw message
Signature · 1 line
2.11.0