From 7d3aa342cef7aa3721bab5157a84bb3d6acce437 Mon Sep 17 00:00:00 2001 From: Radu Pirea Date: Fri, 13 Jul 2018 19:47:33 +0300 Subject: mfd: at91-usart: Add MFD driver for USART This MFD driver is just a wrapper over atmel_serial driver and spi-at91-usart driver. Selection of one of the drivers is based on a property from device tree. If the property is not specified, the default driver is atmel_serial. Signed-off-by: Radu Pirea Reviewed-by: Andy Shevchenko Acked-by: Rob Herring Acked-by: Nicolas Ferre Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 9 ++++++ drivers/mfd/Makefile | 1 + drivers/mfd/at91-usart.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 drivers/mfd/at91-usart.c (limited to 'drivers') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 11841f4b7b2b..0b79c5d04cc9 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -99,6 +99,15 @@ config MFD_AAT2870_CORE additional drivers must be enabled in order to use the functionality of the device. +config MFD_AT91_USART + tristate "AT91 USART Driver" + select MFD_CORE + help + Select this to get support for AT91 USART IP. This is a wrapper + over at91-usart-serial driver and usart-spi-driver. Only one function + can be used at a time. The choice is done at boot time by the probe + function of this MFD driver according to a device tree property. + config MFD_ATMEL_FLEXCOM tristate "Atmel Flexcom (Flexible Serial Communication Unit)" select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 5856a9489cbd..12980a4ad460 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -196,6 +196,7 @@ obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o obj-$(CONFIG_MFD_TPS65090) += tps65090.o obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o +obj-$(CONFIG_MFD_AT91_USART) += at91-usart.o obj-$(CONFIG_MFD_ATMEL_FLEXCOM) += atmel-flexcom.o obj-$(CONFIG_MFD_ATMEL_HLCDC) += atmel-hlcdc.o obj-$(CONFIG_MFD_ATMEL_SMC) += atmel-smc.o diff --git a/drivers/mfd/at91-usart.c b/drivers/mfd/at91-usart.c new file mode 100644 index 000000000000..a4b9929c156f --- /dev/null +++ b/drivers/mfd/at91-usart.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for AT91 USART + * + * Copyright (C) 2018 Microchip Technology + * + * Author: Radu Pirea + * + */ + +#include + +#include +#include +#include + +static struct mfd_cell at91_usart_spi_subdev = { + .name = "at91_usart_spi", + .of_compatible = "microchip,at91sam9g45-usart-spi", + }; + +static struct mfd_cell at91_usart_serial_subdev = { + .name = "atmel_usart_serial", + .of_compatible = "atmel,at91rm9200-usart-serial", + }; + +static int at91_usart_mode_probe(struct platform_device *pdev) +{ + struct mfd_cell cell; + u32 opmode = AT91_USART_MODE_SERIAL; + + device_property_read_u32(&pdev->dev, "atmel,usart-mode", &opmode); + + switch (opmode) { + case AT91_USART_MODE_SPI: + cell = at91_usart_spi_subdev; + break; + case AT91_USART_MODE_SERIAL: + cell = at91_usart_serial_subdev; + break; + default: + dev_err(&pdev->dev, "atmel,usart-mode has an invalid value %u\n", + opmode); + return -EINVAL; + } + + return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO, &cell, 1, + NULL, 0, NULL); +} + +static const struct of_device_id at91_usart_mode_of_match[] = { + { .compatible = "atmel,at91rm9200-usart" }, + { .compatible = "atmel,at91sam9260-usart" }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, at91_usart_mode_of_match); + +static struct platform_driver at91_usart_mfd = { + .probe = at91_usart_mode_probe, + .driver = { + .name = "at91_usart_mode", + .of_match_table = at91_usart_mode_of_match, + }, +}; + +module_platform_driver(at91_usart_mfd); + +MODULE_AUTHOR("Radu Pirea "); +MODULE_DESCRIPTION("AT91 USART MFD driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From e1892546ff662f5491f707ba8a8a3a3e01a84a80 Mon Sep 17 00:00:00 2001 From: Radu Pirea Date: Fri, 13 Jul 2018 19:47:35 +0300 Subject: spi: at91-usart: Add driver for at91-usart as SPI This is the driver for at91-usart in spi mode. The USART IP can be configured to work in many modes and one of them is SPI. The driver was tested on sama5d3-xplained and sama5d4-xplained boards with enc28j60 ethernet controller as slave. Signed-off-by: Radu Pirea Reviewed-by: Andy Shevchenko Reviwed-by: Mark Brown Acked-by: Nicolas Ferre Signed-off-by: Lee Jones --- drivers/spi/Kconfig | 8 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 432 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 441 insertions(+) create mode 100644 drivers/spi/spi-at91-usart.c (limited to 'drivers') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 671d078349cc..2e259d0f4136 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -83,6 +83,14 @@ config SPI_ATMEL This selects a driver for the Atmel SPI Controller, present on many AT91 ARM chips. +config SPI_AT91_USART + tristate "Atmel USART Controller SPI driver" + depends on (ARCH_AT91 || COMPILE_TEST) + depends on MFD_AT91_USART + help + This selects a driver for the AT91 USART Controller as SPI Master, + present on AT91 and SAMA5 SoC series. + config SPI_AU1550 tristate "Au1550/Au1200/Au1300 SPI Controller" depends on MIPS_ALCHEMY diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index a90d55970036..ad094fca36aa 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_SPI_LOOPBACK_TEST) += spi-loopback-test.o obj-$(CONFIG_SPI_ALTERA) += spi-altera.o obj-$(CONFIG_SPI_ARMADA_3700) += spi-armada-3700.o obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o +obj-$(CONFIG_SPI_AT91_USART) += spi-at91-usart.o obj-$(CONFIG_SPI_ATH79) += spi-ath79.o obj-$(CONFIG_SPI_AU1550) += spi-au1550.o obj-$(CONFIG_SPI_AXI_SPI_ENGINE) += spi-axi-spi-engine.o diff --git a/drivers/spi/spi-at91-usart.c b/drivers/spi/spi-at91-usart.c new file mode 100644 index 000000000000..4712bd470c89 --- /dev/null +++ b/drivers/spi/spi-at91-usart.c @@ -0,0 +1,432 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Driver for AT91 USART Controllers as SPI +// +// Copyright (C) 2018 Microchip Technology Inc. +// +// Author: Radu Pirea + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define US_CR 0x00 +#define US_MR 0x04 +#define US_IER 0x08 +#define US_IDR 0x0C +#define US_CSR 0x14 +#define US_RHR 0x18 +#define US_THR 0x1C +#define US_BRGR 0x20 +#define US_VERSION 0xFC + +#define US_CR_RSTRX BIT(2) +#define US_CR_RSTTX BIT(3) +#define US_CR_RXEN BIT(4) +#define US_CR_RXDIS BIT(5) +#define US_CR_TXEN BIT(6) +#define US_CR_TXDIS BIT(7) + +#define US_MR_SPI_MASTER 0x0E +#define US_MR_CHRL GENMASK(7, 6) +#define US_MR_CPHA BIT(8) +#define US_MR_CPOL BIT(16) +#define US_MR_CLKO BIT(18) +#define US_MR_WRDBT BIT(20) +#define US_MR_LOOP BIT(15) + +#define US_IR_RXRDY BIT(0) +#define US_IR_TXRDY BIT(1) +#define US_IR_OVRE BIT(5) + +#define US_BRGR_SIZE BIT(16) + +#define US_MIN_CLK_DIV 0x06 +#define US_MAX_CLK_DIV BIT(16) + +#define US_RESET (US_CR_RSTRX | US_CR_RSTTX) +#define US_DISABLE (US_CR_RXDIS | US_CR_TXDIS) +#define US_ENABLE (US_CR_RXEN | US_CR_TXEN) +#define US_OVRE_RXRDY_IRQS (US_IR_OVRE | US_IR_RXRDY) + +#define US_INIT \ + (US_MR_SPI_MASTER | US_MR_CHRL | US_MR_CLKO | US_MR_WRDBT) + +/* Register access macros */ +#define at91_usart_spi_readl(port, reg) \ + readl_relaxed((port)->regs + US_##reg) +#define at91_usart_spi_writel(port, reg, value) \ + writel_relaxed((value), (port)->regs + US_##reg) + +#define at91_usart_spi_readb(port, reg) \ + readb_relaxed((port)->regs + US_##reg) +#define at91_usart_spi_writeb(port, reg, value) \ + writeb_relaxed((value), (port)->regs + US_##reg) + +struct at91_usart_spi { + struct spi_transfer *current_transfer; + void __iomem *regs; + struct device *dev; + struct clk *clk; + + /*used in interrupt to protect data reading*/ + spinlock_t lock; + + int irq; + unsigned int current_tx_remaining_bytes; + unsigned int current_rx_remaining_bytes; + + u32 spi_clk; + u32 status; + + bool xfer_failed; +}; + +static inline u32 at91_usart_spi_tx_ready(struct at91_usart_spi *aus) +{ + return aus->status & US_IR_TXRDY; +} + +static inline u32 at91_usart_spi_rx_ready(struct at91_usart_spi *aus) +{ + return aus->status & US_IR_RXRDY; +} + +static inline u32 at91_usart_spi_check_overrun(struct at91_usart_spi *aus) +{ + return aus->status & US_IR_OVRE; +} + +static inline u32 at91_usart_spi_read_status(struct at91_usart_spi *aus) +{ + aus->status = at91_usart_spi_readl(aus, CSR); + return aus->status; +} + +static inline void at91_usart_spi_tx(struct at91_usart_spi *aus) +{ + unsigned int len = aus->current_transfer->len; + unsigned int remaining = aus->current_tx_remaining_bytes; + const u8 *tx_buf = aus->current_transfer->tx_buf; + + if (!remaining) + return; + + if (at91_usart_spi_tx_ready(aus)) { + at91_usart_spi_writeb(aus, THR, tx_buf[len - remaining]); + aus->current_tx_remaining_bytes--; + } +} + +static inline void at91_usart_spi_rx(struct at91_usart_spi *aus) +{ + int len = aus->current_transfer->len; + int remaining = aus->current_rx_remaining_bytes; + u8 *rx_buf = aus->current_transfer->rx_buf; + + if (!remaining) + return; + + rx_buf[len - remaining] = at91_usart_spi_readb(aus, RHR); + aus->current_rx_remaining_bytes--; +} + +static inline void +at91_usart_spi_set_xfer_speed(struct at91_usart_spi *aus, + struct spi_transfer *xfer) +{ + at91_usart_spi_writel(aus, BRGR, + DIV_ROUND_UP(aus->spi_clk, xfer->speed_hz)); +} + +static irqreturn_t at91_usart_spi_interrupt(int irq, void *dev_id) +{ + struct spi_controller *controller = dev_id; + struct at91_usart_spi *aus = spi_master_get_devdata(controller); + + spin_lock(&aus->lock); + at91_usart_spi_read_status(aus); + + if (at91_usart_spi_check_overrun(aus)) { + aus->xfer_failed = true; + at91_usart_spi_writel(aus, IDR, US_IR_OVRE | US_IR_RXRDY); + spin_unlock(&aus->lock); + return IRQ_HANDLED; + } + + if (at91_usart_spi_rx_ready(aus)) { + at91_usart_spi_rx(aus); + spin_unlock(&aus->lock); + return IRQ_HANDLED; + } + + spin_unlock(&aus->lock); + + return IRQ_NONE; +} + +static int at91_usart_spi_setup(struct spi_device *spi) +{ + struct at91_usart_spi *aus = spi_master_get_devdata(spi->controller); + u32 *ausd = spi->controller_state; + unsigned int mr = at91_usart_spi_readl(aus, MR); + u8 bits = spi->bits_per_word; + + if (bits != 8) { + dev_dbg(&spi->dev, "Only 8 bits per word are supported\n"); + return -EINVAL; + } + + if (spi->mode & SPI_CPOL) + mr |= US_MR_CPOL; + else + mr &= ~US_MR_CPOL; + + if (spi->mode & SPI_CPHA) + mr |= US_MR_CPHA; + else + mr &= ~US_MR_CPHA; + + if (spi->mode & SPI_LOOP) + mr |= US_MR_LOOP; + else + mr &= ~US_MR_LOOP; + + if (!ausd) { + ausd = kzalloc(sizeof(*ausd), GFP_KERNEL); + if (!ausd) + return -ENOMEM; + + spi->controller_state = ausd; + } + + *ausd = mr; + + dev_dbg(&spi->dev, + "setup: bpw %u mode 0x%x -> mr %d %08x\n", + bits, spi->mode, spi->chip_select, mr); + + return 0; +} + +int at91_usart_spi_transfer_one(struct spi_controller *ctlr, + struct spi_device *spi, + struct spi_transfer *xfer) +{ + struct at91_usart_spi *aus = spi_master_get_devdata(ctlr); + + at91_usart_spi_set_xfer_speed(aus, xfer); + aus->xfer_failed = false; + aus->current_transfer = xfer; + aus->current_tx_remaining_bytes = xfer->len; + aus->current_rx_remaining_bytes = xfer->len; + + while ((aus->current_tx_remaining_bytes || + aus->current_rx_remaining_bytes) && !aus->xfer_failed) { + at91_usart_spi_read_status(aus); + at91_usart_spi_tx(aus); + cpu_relax(); + } + + if (aus->xfer_failed) { + dev_err(aus->dev, "Overrun!\n"); + return -EIO; + } + + return 0; +} + +int at91_usart_spi_prepare_message(struct spi_controller *ctlr, + struct spi_message *message) +{ + struct at91_usart_spi *aus = spi_master_get_devdata(ctlr); + struct spi_device *spi = message->spi; + u32 *ausd = spi->controller_state; + + at91_usart_spi_writel(aus, CR, US_ENABLE); + at91_usart_spi_writel(aus, IER, US_OVRE_RXRDY_IRQS); + at91_usart_spi_writel(aus, MR, *ausd); + + return 0; +} + +int at91_usart_spi_unprepare_message(struct spi_controller *ctlr, + struct spi_message *message) +{ + struct at91_usart_spi *aus = spi_master_get_devdata(ctlr); + + at91_usart_spi_writel(aus, CR, US_RESET | US_DISABLE); + at91_usart_spi_writel(aus, IDR, US_OVRE_RXRDY_IRQS); + + return 0; +} + +static void at91_usart_spi_cleanup(struct spi_device *spi) +{ + struct at91_usart_spi_device *ausd = spi->controller_state; + + spi->controller_state = NULL; + kfree(ausd); +} + +static void at91_usart_spi_init(struct at91_usart_spi *aus) +{ + at91_usart_spi_writel(aus, MR, US_INIT); + at91_usart_spi_writel(aus, CR, US_RESET | US_DISABLE); +} + +static int at91_usart_gpio_setup(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.parent->of_node; + int i; + int ret; + int nb; + + if (!np) + return -EINVAL; + + nb = of_gpio_named_count(np, "cs-gpios"); + for (i = 0; i < nb; i++) { + int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); + + if (cs_gpio < 0) + return cs_gpio; + + if (gpio_is_valid(cs_gpio)) { + ret = devm_gpio_request_one(&pdev->dev, cs_gpio, + GPIOF_DIR_OUT, + dev_name(&pdev->dev)); + if (ret) + return ret; + } + } + + return 0; +} + +static int at91_usart_spi_probe(struct platform_device *pdev) +{ + struct resource *regs; + struct spi_controller *controller; + struct at91_usart_spi *aus; + struct clk *clk; + int irq; + int ret; + + regs = platform_get_resource(to_platform_device(pdev->dev.parent), + IORESOURCE_MEM, 0); + if (!regs) + return -EINVAL; + + irq = platform_get_irq(to_platform_device(pdev->dev.parent), 0); + if (irq < 0) + return irq; + + clk = devm_clk_get(pdev->dev.parent, "usart"); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + ret = -ENOMEM; + controller = spi_alloc_master(&pdev->dev, sizeof(*aus)); + if (!controller) + goto at91_usart_spi_probe_fail; + + ret = at91_usart_gpio_setup(pdev); + if (ret) + goto at91_usart_spi_probe_fail; + + controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP | SPI_CS_HIGH; + controller->dev.of_node = pdev->dev.parent->of_node; + controller->bits_per_word_mask = SPI_BPW_MASK(8); + controller->setup = at91_usart_spi_setup; + controller->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX; + controller->transfer_one = at91_usart_spi_transfer_one; + controller->prepare_message = at91_usart_spi_prepare_message; + controller->unprepare_message = at91_usart_spi_unprepare_message; + controller->cleanup = at91_usart_spi_cleanup; + controller->max_speed_hz = DIV_ROUND_UP(clk_get_rate(clk), + US_MIN_CLK_DIV); + controller->min_speed_hz = DIV_ROUND_UP(clk_get_rate(clk), + US_MAX_CLK_DIV); + platform_set_drvdata(pdev, controller); + + aus = spi_master_get_devdata(controller); + + aus->dev = &pdev->dev; + aus->regs = devm_ioremap_resource(&pdev->dev, regs); + if (IS_ERR(aus->regs)) { + ret = PTR_ERR(aus->regs); + goto at91_usart_spi_probe_fail; + } + + aus->irq = irq; + aus->clk = clk; + + ret = devm_request_irq(&pdev->dev, irq, at91_usart_spi_interrupt, 0, + dev_name(&pdev->dev), controller); + if (ret) + goto at91_usart_spi_probe_fail; + + ret = clk_prepare_enable(clk); + if (ret) + goto at91_usart_spi_probe_fail; + + aus->spi_clk = clk_get_rate(clk); + at91_usart_spi_init(aus); + + spin_lock_init(&aus->lock); + ret = devm_spi_register_master(&pdev->dev, controller); + if (ret) + goto at91_usart_fail_register_master; + + dev_info(&pdev->dev, + "AT91 USART SPI Controller version 0x%x at %pa (irq %d)\n", + at91_usart_spi_readl(aus, VERSION), + ®s->start, irq); + + return 0; + +at91_usart_fail_register_master: + clk_disable_unprepare(clk); +at91_usart_spi_probe_fail: + spi_master_put(controller); + return ret; +} + +static int at91_usart_spi_remove(struct platform_device *pdev) +{ + struct spi_controller *ctlr = platform_get_drvdata(pdev); + struct at91_usart_spi *aus = spi_master_get_devdata(ctlr); + + clk_disable_unprepare(aus->clk); + + return 0; +} + +static const struct of_device_id at91_usart_spi_dt_ids[] = { + { .compatible = "microchip,at91sam9g45-usart-spi"}, + { /* sentinel */} +}; + +MODULE_DEVICE_TABLE(of, at91_usart_spi_dt_ids); + +static struct platform_driver at91_usart_spi_driver = { + .driver = { + .name = "at91_usart_spi", + }, + .probe = at91_usart_spi_probe, + .remove = at91_usart_spi_remove, +}; + +module_platform_driver(at91_usart_spi_driver); + +MODULE_DESCRIPTION("Microchip AT91 USART SPI Controller driver"); +MODULE_AUTHOR("Radu Pirea "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:at91_usart_spi"); -- cgit v1.2.3 From c24d25317a7c6bb3053d4c193b3cf57d1e9a3e4b Mon Sep 17 00:00:00 2001 From: Radu Pirea Date: Fri, 13 Jul 2018 19:47:36 +0300 Subject: tty/serial: atmel: Change the driver to work under at91-usart MFD This patch modifies the place where resources and device tree properties are searched. Signed-off-by: Radu Pirea Reviewed-by: Andy Shevchenko Acked-by: Richard Genoud Acked-by: Nicolas Ferre Acked-by: Greg Kroah-Hartman Signed-off-by: Lee Jones --- drivers/tty/serial/Kconfig | 1 + drivers/tty/serial/atmel_serial.c | 42 +++++++++++++++++++++++++-------------- 2 files changed, 28 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index df8bd0c7b97d..32886c304641 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -118,6 +118,7 @@ config SERIAL_ATMEL depends on ARCH_AT91 || COMPILE_TEST select SERIAL_CORE select SERIAL_MCTRL_GPIO if GPIOLIB + select MFD_AT91_USART help This enables the driver for the on-chip UARTs of the Atmel AT91 processors. diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 8e4428725848..267d4d1de3f8 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -193,8 +193,7 @@ static struct console atmel_console; #if defined(CONFIG_OF) static const struct of_device_id atmel_serial_dt_ids[] = { - { .compatible = "atmel,at91rm9200-usart" }, - { .compatible = "atmel,at91sam9260-usart" }, + { .compatible = "atmel,at91rm9200-usart-serial" }, { /* sentinel */ } }; #endif @@ -915,6 +914,7 @@ static void atmel_tx_dma(struct uart_port *port) static int atmel_prepare_tx_dma(struct uart_port *port) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + struct device *mfd_dev = port->dev->parent; dma_cap_mask_t mask; struct dma_slave_config config; int ret, nent; @@ -922,7 +922,7 @@ static int atmel_prepare_tx_dma(struct uart_port *port) dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); - atmel_port->chan_tx = dma_request_slave_channel(port->dev, "tx"); + atmel_port->chan_tx = dma_request_slave_channel(mfd_dev, "tx"); if (atmel_port->chan_tx == NULL) goto chan_err; dev_info(port->dev, "using %s for tx DMA transfers\n", @@ -1093,6 +1093,7 @@ static void atmel_rx_from_dma(struct uart_port *port) static int atmel_prepare_rx_dma(struct uart_port *port) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + struct device *mfd_dev = port->dev->parent; struct dma_async_tx_descriptor *desc; dma_cap_mask_t mask; struct dma_slave_config config; @@ -1104,7 +1105,7 @@ static int atmel_prepare_rx_dma(struct uart_port *port) dma_cap_zero(mask); dma_cap_set(DMA_CYCLIC, mask); - atmel_port->chan_rx = dma_request_slave_channel(port->dev, "rx"); + atmel_port->chan_rx = dma_request_slave_channel(mfd_dev, "rx"); if (atmel_port->chan_rx == NULL) goto chan_err; dev_info(port->dev, "using %s for rx DMA transfers\n", @@ -2222,8 +2223,8 @@ static const char *atmel_type(struct uart_port *port) */ static void atmel_release_port(struct uart_port *port) { - struct platform_device *pdev = to_platform_device(port->dev); - int size = pdev->resource[0].end - pdev->resource[0].start + 1; + struct platform_device *mpdev = to_platform_device(port->dev->parent); + int size = resource_size(mpdev->resource); release_mem_region(port->mapbase, size); @@ -2238,8 +2239,8 @@ static void atmel_release_port(struct uart_port *port) */ static int atmel_request_port(struct uart_port *port) { - struct platform_device *pdev = to_platform_device(port->dev); - int size = pdev->resource[0].end - pdev->resource[0].start + 1; + struct platform_device *mpdev = to_platform_device(port->dev->parent); + int size = resource_size(mpdev->resource); if (!request_mem_region(port->mapbase, size, "atmel_serial")) return -EBUSY; @@ -2341,27 +2342,28 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port, { int ret; struct uart_port *port = &atmel_port->uart; + struct platform_device *mpdev = to_platform_device(pdev->dev.parent); atmel_init_property(atmel_port, pdev); atmel_set_ops(port); - uart_get_rs485_mode(&pdev->dev, &port->rs485); + uart_get_rs485_mode(&mpdev->dev, &port->rs485); port->iotype = UPIO_MEM; port->flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP; port->ops = &atmel_pops; port->fifosize = 1; port->dev = &pdev->dev; - port->mapbase = pdev->resource[0].start; - port->irq = pdev->resource[1].start; + port->mapbase = mpdev->resource[0].start; + port->irq = mpdev->resource[1].start; port->rs485_config = atmel_config_rs485; - port->membase = NULL; + port->membase = NULL; memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring)); /* for console, the clock could already be configured */ if (!atmel_port->clk) { - atmel_port->clk = clk_get(&pdev->dev, "usart"); + atmel_port->clk = clk_get(&mpdev->dev, "usart"); if (IS_ERR(atmel_port->clk)) { ret = PTR_ERR(atmel_port->clk); atmel_port->clk = NULL; @@ -2694,13 +2696,22 @@ static void atmel_serial_probe_fifos(struct atmel_uart_port *atmel_port, static int atmel_serial_probe(struct platform_device *pdev) { struct atmel_uart_port *atmel_port; - struct device_node *np = pdev->dev.of_node; + struct device_node *np = pdev->dev.parent->of_node; void *data; int ret = -ENODEV; bool rs485_enabled; BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1)); + /* + * In device tree there is no node with "atmel,at91rm9200-usart-serial" + * as compatible string. This driver is probed by at91-usart mfd driver + * which is just a wrapper over the atmel_serial driver and + * spi-at91-usart driver. All attributes needed by this driver are + * found in of_node of parent. + */ + pdev->dev.of_node = np; + ret = of_alias_get_id(np, "serial"); if (ret < 0) /* port id not found in platform data nor device-tree aliases: @@ -2836,6 +2847,7 @@ static int atmel_serial_remove(struct platform_device *pdev) clk_put(atmel_port->clk); atmel_port->clk = NULL; + pdev->dev.of_node = NULL; return ret; } @@ -2846,7 +2858,7 @@ static struct platform_driver atmel_serial_driver = { .suspend = atmel_serial_suspend, .resume = atmel_serial_resume, .driver = { - .name = "atmel_usart", + .name = "atmel_usart_serial", .of_match_table = of_match_ptr(atmel_serial_dt_ids), }, }; -- cgit v1.2.3 From 259e0a00dc7c74617a8b2e33ae3604e4ffaed9cd Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 11 Sep 2018 11:38:50 +0100 Subject: spi: at91-usart: Make local functions static Suggested-by: Radu Nicolae Pirea Signed-off-by: Lee Jones --- drivers/spi/spi-at91-usart.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-at91-usart.c b/drivers/spi/spi-at91-usart.c index 4712bd470c89..a924657642fa 100644 --- a/drivers/spi/spi-at91-usart.c +++ b/drivers/spi/spi-at91-usart.c @@ -215,9 +215,9 @@ static int at91_usart_spi_setup(struct spi_device *spi) return 0; } -int at91_usart_spi_transfer_one(struct spi_controller *ctlr, - struct spi_device *spi, - struct spi_transfer *xfer) +static int at91_usart_spi_transfer_one(struct spi_controller *ctlr, + struct spi_device *spi, + struct spi_transfer *xfer) { struct at91_usart_spi *aus = spi_master_get_devdata(ctlr); @@ -242,8 +242,8 @@ int at91_usart_spi_transfer_one(struct spi_controller *ctlr, return 0; } -int at91_usart_spi_prepare_message(struct spi_controller *ctlr, - struct spi_message *message) +static int at91_usart_spi_prepare_message(struct spi_controller *ctlr, + struct spi_message *message) { struct at91_usart_spi *aus = spi_master_get_devdata(ctlr); struct spi_device *spi = message->spi; @@ -256,8 +256,8 @@ int at91_usart_spi_prepare_message(struct spi_controller *ctlr, return 0; } -int at91_usart_spi_unprepare_message(struct spi_controller *ctlr, - struct spi_message *message) +static int at91_usart_spi_unprepare_message(struct spi_controller *ctlr, + struct spi_message *message) { struct at91_usart_spi *aus = spi_master_get_devdata(ctlr); -- cgit v1.2.3 From 65b80dfffeabd4eb253b93d07eadde4d89c18511 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 11 Sep 2018 11:34:27 +0100 Subject: mfd: at91-usart: Include Device Tree header Will ensure 'of_device_id' is declared. Signed-off-by: Lee Jones --- drivers/mfd/at91-usart.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/at91-usart.c b/drivers/mfd/at91-usart.c index a4b9929c156f..d20747f612c1 100644 --- a/drivers/mfd/at91-usart.c +++ b/drivers/mfd/at91-usart.c @@ -12,6 +12,7 @@ #include #include +#include #include static struct mfd_cell at91_usart_spi_subdev = { -- cgit v1.2.3 From 9612f8f503804d2fd2f63aa6ba1e58bba4612d96 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sun, 9 Sep 2018 22:48:58 +0200 Subject: mfd: menelaus: Fix possible race condition and leak The IRQ work is added before the struct rtc is allocated and registered, but this struct is used in the IRQ handler. This may lead to a NULL pointer dereference. Switch to devm_rtc_allocate_device/rtc_register_device to allocate the rtc before calling menelaus_add_irq_work. Also, this solves a possible leak as the RTC is never released. Signed-off-by: Alexandre Belloni Signed-off-by: Lee Jones --- drivers/mfd/menelaus.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c index 29b7164a823b..d28ebe7ecd21 100644 --- a/drivers/mfd/menelaus.c +++ b/drivers/mfd/menelaus.c @@ -1094,6 +1094,7 @@ static void menelaus_rtc_alarm_work(struct menelaus_chip *m) static inline void menelaus_rtc_init(struct menelaus_chip *m) { int alarm = (m->client->irq > 0); + int err; /* assume 32KDETEN pin is pulled high */ if (!(menelaus_read_reg(MENELAUS_OSC_CTRL) & 0x80)) { @@ -1101,6 +1102,12 @@ static inline void menelaus_rtc_init(struct menelaus_chip *m) return; } + m->rtc = devm_rtc_allocate_device(&m->client->dev); + if (IS_ERR(m->rtc)) + return; + + m->rtc->ops = &menelaus_rtc_ops; + /* support RTC alarm; it can issue wakeups */ if (alarm) { if (menelaus_add_irq_work(MENELAUS_RTCALM_IRQ, @@ -1125,10 +1132,8 @@ static inline void menelaus_rtc_init(struct menelaus_chip *m) menelaus_write_reg(MENELAUS_RTC_CTRL, m->rtc_control); } - m->rtc = rtc_device_register(DRIVER_NAME, - &m->client->dev, - &menelaus_rtc_ops, THIS_MODULE); - if (IS_ERR(m->rtc)) { + err = rtc_register_device(m->rtc); + if (err) { if (alarm) { menelaus_remove_irq_work(MENELAUS_RTCALM_IRQ); device_init_wakeup(&m->client->dev, 0); -- cgit v1.2.3 From cec945c293fb52ac1a1ac88703422d3bc1d8f10a Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Sat, 30 Jun 2018 16:03:14 +0530 Subject: mfd: ti_am335x_tscadc: Don't mark TSCADC MFD as wakeup capable Currently tscadc MFD is marked as wakeup capable which incorrect because, its actually touch event by child TSC device that wakes up the system. Therefore, remove device_init_wakeup() call that marks TSCADC device as wakeup capable in favor of moving to mark TSC input device as wakeup capable later. Signed-off-by: Vignesh R Signed-off-by: Lee Jones --- drivers/mfd/ti_am335x_tscadc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index 7a30546880a4..ee3ffd96f5d2 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -269,7 +269,6 @@ static int ti_tscadc_probe(struct platform_device *pdev) if (err < 0) goto err_disable_clk; - device_init_wakeup(&pdev->dev, true); platform_set_drvdata(pdev, tscadc); return 0; -- cgit v1.2.3 From 333e07ec4b3397f16f34b2eabae703a2885f3558 Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Sat, 30 Jun 2018 16:03:15 +0530 Subject: Input: ti_am335x_tsc: Mark TSC device as wakeup source Instead of TSCADC MFD device, mark TSC as wakeup source and change all wakeup related PM calls to operate on TSC device. Signed-off-by: Vignesh R Acked-by: Dmitry Torokhov Signed-off-by: Lee Jones --- drivers/input/touchscreen/ti_am335x_tsc.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index b86c1e5fbc11..a4f25a915ffc 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -46,6 +46,7 @@ static const int config_pins[] = { struct titsc { struct input_dev *input; struct ti_tscadc_dev *mfd_tscadc; + struct device *dev; unsigned int irq; unsigned int wires; unsigned int x_plate_resistance; @@ -276,7 +277,7 @@ static irqreturn_t titsc_irq(int irq, void *dev) if (status & IRQENB_HW_PEN) { ts_dev->pen_down = true; irqclr |= IRQENB_HW_PEN; - pm_stay_awake(ts_dev->mfd_tscadc->dev); + pm_stay_awake(ts_dev->dev); } if (status & IRQENB_PENUP) { @@ -286,7 +287,7 @@ static irqreturn_t titsc_irq(int irq, void *dev) input_report_key(input_dev, BTN_TOUCH, 0); input_report_abs(input_dev, ABS_PRESSURE, 0); input_sync(input_dev); - pm_relax(ts_dev->mfd_tscadc->dev); + pm_relax(ts_dev->dev); } else { ts_dev->pen_down = true; } @@ -422,6 +423,7 @@ static int titsc_probe(struct platform_device *pdev) ts_dev->mfd_tscadc = tscadc_dev; ts_dev->input = input_dev; ts_dev->irq = tscadc_dev->irq; + ts_dev->dev = &pdev->dev; err = titsc_parse_dt(pdev, ts_dev); if (err) { @@ -436,6 +438,8 @@ static int titsc_probe(struct platform_device *pdev) goto err_free_mem; } + device_init_wakeup(&pdev->dev, true); + titsc_writel(ts_dev, REG_IRQSTATUS, TSC_IRQENB_MASK); titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES); titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_EOS); @@ -467,6 +471,7 @@ static int titsc_probe(struct platform_device *pdev) return 0; err_free_irq: + device_init_wakeup(&pdev->dev, false); free_irq(ts_dev->irq, ts_dev); err_free_mem: input_free_device(input_dev); @@ -479,6 +484,7 @@ static int titsc_remove(struct platform_device *pdev) struct titsc *ts_dev = platform_get_drvdata(pdev); u32 steps; + device_init_wakeup(&pdev->dev, false); free_irq(ts_dev->irq, ts_dev); /* total steps followed by the enable mask */ @@ -499,7 +505,7 @@ static int __maybe_unused titsc_suspend(struct device *dev) unsigned int idle; tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev)); - if (device_may_wakeup(tscadc_dev->dev)) { + if (device_may_wakeup(dev)) { titsc_writel(ts_dev, REG_IRQSTATUS, TSC_IRQENB_MASK); idle = titsc_readl(ts_dev, REG_IRQENABLE); titsc_writel(ts_dev, REG_IRQENABLE, @@ -515,11 +521,11 @@ static int __maybe_unused titsc_resume(struct device *dev) struct ti_tscadc_dev *tscadc_dev; tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev)); - if (device_may_wakeup(tscadc_dev->dev)) { + if (device_may_wakeup(dev)) { titsc_writel(ts_dev, REG_IRQWAKEUP, 0x00); titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN); - pm_relax(ts_dev->mfd_tscadc->dev); + pm_relax(dev); } titsc_step_config(ts_dev); titsc_writel(ts_dev, REG_FIFO0THR, -- cgit v1.2.3 From c974ac771479327b5424f60d58845e31daddadea Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Sat, 30 Jun 2018 16:03:16 +0530 Subject: mfd: ti_am335x_tscadc: Keep ADC interface on if child is wakeup capable If a child device like touchscreen is wakeup capable, then keep ADC interface on, so that a touching resistive screen will generate wakeup event to the system. Signed-off-by: Vignesh R Signed-off-by: Lee Jones --- drivers/mfd/ti_am335x_tscadc.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index ee3ffd96f5d2..c2d47d78705b 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -293,11 +293,24 @@ static int ti_tscadc_remove(struct platform_device *pdev) return 0; } +static int __maybe_unused ti_tscadc_can_wakeup(struct device *dev, void *data) +{ + return device_may_wakeup(dev); +} + static int __maybe_unused tscadc_suspend(struct device *dev) { struct ti_tscadc_dev *tscadc = dev_get_drvdata(dev); regmap_write(tscadc->regmap, REG_SE, 0x00); + if (device_for_each_child(dev, NULL, ti_tscadc_can_wakeup)) { + u32 ctrl; + + regmap_read(tscadc->regmap, REG_CTRL, &ctrl); + ctrl &= ~(CNTRLREG_POWERDOWN); + ctrl |= CNTRLREG_TSCSSENB; + regmap_write(tscadc->regmap, REG_CTRL, ctrl); + } pm_runtime_put_sync(dev); return 0; -- cgit v1.2.3 From 9eea8326f4e6862637b94f09deb2ec9f2b50e1bc Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Sat, 30 Jun 2018 16:03:17 +0530 Subject: iio: adc: ti_am335x_adc: Disable ADC during suspend unconditionally Parent MFD device takes care of enabling ADC interface whenever touchscreen is marked wakeup capable. Therefore, unconditionally disable ADC interface during system suspend to save power in case of system with just ADC and no TSC. Signed-off-by: Vignesh R Acked-by: Jonathan Cameron Signed-off-by: Lee Jones --- drivers/iio/adc/ti_am335x_adc.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 80df5a377d30..cafb1dcadc48 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -693,16 +693,12 @@ static int __maybe_unused tiadc_suspend(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct tiadc_device *adc_dev = iio_priv(indio_dev); - struct ti_tscadc_dev *tscadc_dev; unsigned int idle; - tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev)); - if (!device_may_wakeup(tscadc_dev->dev)) { - idle = tiadc_readl(adc_dev, REG_CTRL); - idle &= ~(CNTRLREG_TSCSSENB); - tiadc_writel(adc_dev, REG_CTRL, (idle | - CNTRLREG_POWERDOWN)); - } + idle = tiadc_readl(adc_dev, REG_CTRL); + idle &= ~(CNTRLREG_TSCSSENB); + tiadc_writel(adc_dev, REG_CTRL, (idle | + CNTRLREG_POWERDOWN)); return 0; } -- cgit v1.2.3 From 7a39915b723ae46e78c5189dfb3fc889df976a8d Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Sat, 30 Jun 2018 16:03:18 +0530 Subject: Input: ti_am335x_tsc: Mark IRQ as wakeup capable On AM335x, ti_am335x_tsc can wake up the system from suspend, mark the IRQ as wakeup capable, so that device irq is not disabled during system suspend. Signed-off-by: Vignesh R Acked-by: Dmitry Torokhov Signed-off-by: Lee Jones --- drivers/input/touchscreen/ti_am335x_tsc.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index a4f25a915ffc..9e8684ab48f4 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -439,6 +440,9 @@ static int titsc_probe(struct platform_device *pdev) } device_init_wakeup(&pdev->dev, true); + err = dev_pm_set_wake_irq(&pdev->dev, ts_dev->irq); + if (err) + dev_err(&pdev->dev, "irq wake enable failed.\n"); titsc_writel(ts_dev, REG_IRQSTATUS, TSC_IRQENB_MASK); titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES); @@ -471,6 +475,7 @@ static int titsc_probe(struct platform_device *pdev) return 0; err_free_irq: + dev_pm_clear_wake_irq(&pdev->dev); device_init_wakeup(&pdev->dev, false); free_irq(ts_dev->irq, ts_dev); err_free_mem: @@ -484,6 +489,7 @@ static int titsc_remove(struct platform_device *pdev) struct titsc *ts_dev = platform_get_drvdata(pdev); u32 steps; + dev_pm_clear_wake_irq(&pdev->dev); device_init_wakeup(&pdev->dev, false); free_irq(ts_dev->irq, ts_dev); -- cgit v1.2.3 From 39b27ad9c71cb72b07c9cd85191a8fe723e5b21a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 7 Aug 2018 18:11:22 +0200 Subject: mfd: sec-core: Add SPDX license identifiers Replace GPL v2.0+ license statements with SPDX license identifiers. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/sec-core.c | 16 ++++------------ drivers/mfd/sec-irq.c | 16 ++++------------ 2 files changed, 8 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 9613b4257302..e0835c9df7a1 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -1,15 +1,7 @@ -/* - * sec-core.c - * - * Copyright (c) 2012 Samsung Electronics Co., Ltd - * http://www.samsung.com - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// Copyright (c) 2012 Samsung Electronics Co., Ltd +// http://www.samsung.com #include #include diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index 5eb59c233d52..295d24d4501d 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c @@ -1,15 +1,7 @@ -/* - * sec-irq.c - * - * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd - * http://www.samsung.com - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// Copyright (c) 2011-2014 Samsung Electronics Co., Ltd +// http://www.samsung.com #include #include -- cgit v1.2.3 From d7d8d7a2405f8b6296660648e893fc3442269d81 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 7 Aug 2018 18:11:23 +0200 Subject: mfd: maxim: Add SPDX license identifiers Replace GPL v2.0+ license statements with SPDX license identifiers. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/max14577.c | 28 +++++++++------------------- drivers/mfd/max77686.c | 32 +++++++++----------------------- drivers/mfd/max77693.c | 34 ++++++++++------------------------ drivers/mfd/max77843.c | 19 +++++++------------ drivers/mfd/max8997-irq.c | 30 ++++++++---------------------- drivers/mfd/max8997.c | 30 ++++++++---------------------- drivers/mfd/max8998-irq.c | 18 ++++++------------ drivers/mfd/max8998.c | 28 +++++++--------------------- 8 files changed, 64 insertions(+), 155 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c index 6cbe96b28f42..ebb13d5de530 100644 --- a/drivers/mfd/max14577.c +++ b/drivers/mfd/max14577.c @@ -1,22 +1,12 @@ -/* - * max14577.c - mfd core driver for the Maxim 14577/77836 - * - * Copyright (C) 2014 Samsung Electronics - * Chanwoo Choi - * Krzysztof Kozlowski - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This driver is based on max8997.c - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// max14577.c - mfd core driver for the Maxim 14577/77836 +// +// Copyright (C) 2014 Samsung Electronics +// Chanwoo Choi +// Krzysztof Kozlowski +// +// This driver is based on max8997.c #include #include diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index b0e8e13c0049..71faf503844b 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -1,26 +1,12 @@ -/* - * max77686.c - mfd core driver for the Maxim 77686/802 - * - * Copyright (C) 2012 Samsung Electronics - * Chiwoong Byun - * Jonghwa Lee - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * This driver is based on max8997.c - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// max77686.c - mfd core driver for the Maxim 77686/802 +// +// Copyright (C) 2012 Samsung Electronics +// Chiwoong Byun +// Jonghwa Lee +// +//This driver is based on max8997.c #include #include diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index 1c05ea0cba61..901d99d65924 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -1,27 +1,13 @@ -/* - * max77693.c - mfd core driver for the MAX 77693 - * - * Copyright (C) 2012 Samsung Electronics - * SangYoung Son - * - * This program is not provided / owned by Maxim Integrated Products. - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * This driver is based on max8997.c - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// max77693.c - mfd core driver for the MAX 77693 +// +// Copyright (C) 2012 Samsung Electronics +// SangYoung Son +// +// This program is not provided / owned by Maxim Integrated Products. +// +// This driver is based on max8997.c #include #include diff --git a/drivers/mfd/max77843.c b/drivers/mfd/max77843.c index da9612dbb222..25cbb2242b26 100644 --- a/drivers/mfd/max77843.c +++ b/drivers/mfd/max77843.c @@ -1,15 +1,10 @@ -/* - * MFD core driver for the Maxim MAX77843 - * - * Copyright (C) 2015 Samsung Electronics - * Author: Jaewon Kim - * Author: Beomho Seo - * - * 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; either version 2 of the License, or - * (at your option) any later version. - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// MFD core driver for the Maxim MAX77843 +// +// Copyright (C) 2015 Samsung Electronics +// Author: Jaewon Kim +// Author: Beomho Seo #include #include diff --git a/drivers/mfd/max8997-irq.c b/drivers/mfd/max8997-irq.c index 326f17b632a7..93a3b1698d9c 100644 --- a/drivers/mfd/max8997-irq.c +++ b/drivers/mfd/max8997-irq.c @@ -1,25 +1,11 @@ -/* - * max8997-irq.c - Interrupt controller support for MAX8997 - * - * Copyright (C) 2011 Samsung Electronics Co.Ltd - * MyungJoo Ham - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * This driver is based on max8998-irq.c - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// max8997-irq.c - Interrupt controller support for MAX8997 +// +// Copyright (C) 2011 Samsung Electronics Co.Ltd +// MyungJoo Ham +// +// This driver is based on max8998-irq.c #include #include diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index 3f554c447521..8dbae31911a1 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -1,25 +1,11 @@ -/* - * max8997.c - mfd core driver for the Maxim 8966 and 8997 - * - * Copyright (C) 2011 Samsung Electronics - * MyungJoo Ham - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * This driver is based on max8998.c - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// max8997.c - mfd core driver for the Maxim 8966 and 8997 +// +// Copyright (C) 2011 Samsung Electronics +// MyungJoo Ham +// +// This driver is based on max8998.c #include #include diff --git a/drivers/mfd/max8998-irq.c b/drivers/mfd/max8998-irq.c index 90bad9ffa7e2..83b6f510bc05 100644 --- a/drivers/mfd/max8998-irq.c +++ b/drivers/mfd/max8998-irq.c @@ -1,15 +1,9 @@ -/* - * Interrupt controller support for MAX8998 - * - * Copyright (C) 2010 Samsung Electronics Co.Ltd - * Author: Joonyoung Shim - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// Interrupt controller support for MAX8998 +// +// Copyright (C) 2010 Samsung Electronics Co.Ltd +// Author: Joonyoung Shim #include #include diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c index b1d3f70782d9..56409df120f8 100644 --- a/drivers/mfd/max8998.c +++ b/drivers/mfd/max8998.c @@ -1,24 +1,10 @@ -/* - * max8998.c - mfd core driver for the Maxim 8998 - * - * Copyright (C) 2009-2010 Samsung Electronics - * Kyungmin Park - * Marek Szyprowski - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// max8998.c - mfd core driver for the Maxim 8998 +// +// Copyright (C) 2009-2010 Samsung Electronics +// Kyungmin Park +// Marek Szyprowski #include #include -- cgit v1.2.3 From 838a724072d37c45d717ca38252496253d4c09bc Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 7 Aug 2018 18:11:24 +0200 Subject: mfd: sec-core: Fix indentation of Kconfig description The indentation should be a tab followed by two spaces. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 0b79c5d04cc9..7ef170dc766d 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1038,10 +1038,10 @@ config MFD_SEC_CORE select REGMAP_I2C select REGMAP_IRQ help - Support for the Samsung Electronics MFD series. - This driver provides common support for accessing the device, - additional drivers must be enabled in order to use the functionality - of the device + Support for the Samsung Electronics MFD series. + This driver provides common support for accessing the device, + additional drivers must be enabled in order to use the functionality + of the device config MFD_SI476X_CORE tristate "Silicon Laboratories 4761/64/68 AM/FM radio." -- cgit v1.2.3 From eef0594aee29f289b0ddda02be7ccdbc5dd5956a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 7 Aug 2018 18:11:25 +0200 Subject: mfd: sec-core: Allow building as module The main MFD driver for Samsung PMICs (S2MPSXX, S5M876X) used with Exynos SoCs can be compiled and used as a module. The dependent clock, regulator and RTC drivers already can be built as a module. Building entire set of drivers as modules might require using initial ramdisk and can make booting process longer (due to probe deferrals). However adding such option is useful for testing and for multi-platform configurations. This also add required module authors to sec-irq.c file based on recent main contributors. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 11 +++++++++-- drivers/mfd/sec-irq.c | 8 ++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 7ef170dc766d..8c5dfdce4326 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1032,17 +1032,24 @@ config MFD_RN5T618 functionality of the device. config MFD_SEC_CORE - bool "SAMSUNG Electronics PMIC Series Support" + tristate "SAMSUNG Electronics PMIC Series Support" depends on I2C=y select MFD_CORE select REGMAP_I2C select REGMAP_IRQ help - Support for the Samsung Electronics MFD series. + Support for the Samsung Electronics PMIC devices coming + usually along with Samsung Exynos SoC chipset. This driver provides common support for accessing the device, additional drivers must be enabled in order to use the functionality of the device + To compile this driver as a module, choose M here: the + module will be called sec-core. + Have in mind that important core drivers (like regulators) depend + on this driver so building this as a module might require proper + initial ramdisk or might not boot up as well in certain scenarios. + config MFD_SI476X_CORE tristate "Silicon Laboratories 4761/64/68 AM/FM radio." depends on I2C diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index 295d24d4501d..ad0099077e7e 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -493,3 +494,10 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic) return 0; } +EXPORT_SYMBOL_GPL(sec_irq_init); + +MODULE_AUTHOR("Sangbeom Kim "); +MODULE_AUTHOR("Chanwoo Choi "); +MODULE_AUTHOR("Krzysztof Kozlowski "); +MODULE_DESCRIPTION("Interrupt support for the S5M MFD"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 4ded11d1cf128db8b5d5b57db3a50dd124358520 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 14 Aug 2018 13:31:59 +0200 Subject: mfd: adp5520: Update MODULE AUTHOR email address No functional changes Signed-off-by: Michael Hennerich Signed-off-by: Lee Jones --- drivers/mfd/adp5520.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c index d817f202da5b..be0497b96720 100644 --- a/drivers/mfd/adp5520.c +++ b/drivers/mfd/adp5520.c @@ -360,6 +360,6 @@ static struct i2c_driver adp5520_driver = { module_i2c_driver(adp5520_driver); -MODULE_AUTHOR("Michael Hennerich "); +MODULE_AUTHOR("Michael Hennerich "); MODULE_DESCRIPTION("ADP5520(01) PMIC-MFD Driver"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 61cc15dac01ae84281222452e338ca060179d8b1 Mon Sep 17 00:00:00 2001 From: RaviChandra Sadineni Date: Mon, 20 Aug 2018 08:34:19 -0700 Subject: mfd: cros_ec: Check for mkbp events on resume only if supported. Currently on every resume we check for mkbp events and notify the clients. This helps in identifying the wakeup sources. But on devices that do not support mkbp protocol, we might end up querying key state of the keyboard in a loop which blocks the resume. Instead check for events only if mkbp is supported. Signed-off-by: RaviChandra Sadineni Reported-by: Marek Szyprowski Tested-by: Marek Szyprowski Signed-off-by: Lee Jones --- drivers/mfd/cros_ec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c index 65a9757a6d21..fe6f83766144 100644 --- a/drivers/mfd/cros_ec.c +++ b/drivers/mfd/cros_ec.c @@ -218,7 +218,8 @@ EXPORT_SYMBOL(cros_ec_suspend); static void cros_ec_report_events_during_suspend(struct cros_ec_device *ec_dev) { - while (cros_ec_get_next_event(ec_dev, NULL) > 0) + while (ec_dev->mkbp_event_supported && + cros_ec_get_next_event(ec_dev, NULL) > 0) blocking_notifier_call_chain(&ec_dev->event_notifier, 1, ec_dev); } -- cgit v1.2.3 From 6b269a41a4520f7eb639e61a45ebbb9c9267d5e0 Mon Sep 17 00:00:00 2001 From: Sapthagiri Baratam Date: Tue, 21 Aug 2018 19:52:44 +0530 Subject: mfd: arizona: Correct calling of runtime_put_sync Don't call runtime_put_sync when clk32k_ref is ARIZONA_32KZ_MCLK2 as there is no corresponding runtime_get_sync call. MCLK1 is not in the AoD power domain so if it is used as 32kHz clock source we need to hold a runtime PM reference to keep the device from going into low power mode. Fixes: cdd8da8cc66b ("mfd: arizona: Add gating of external MCLKn clocks") Signed-off-by: Sapthagiri Baratam Acked-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/arizona-core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 5f1e37d23943..057906e3c16e 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -52,8 +52,10 @@ int arizona_clk32k_enable(struct arizona *arizona) if (ret != 0) goto err_ref; ret = clk_prepare_enable(arizona->mclk[ARIZONA_MCLK1]); - if (ret != 0) - goto err_pm; + if (ret != 0) { + pm_runtime_put_sync(arizona->dev); + goto err_ref; + } break; case ARIZONA_32KZ_MCLK2: ret = clk_prepare_enable(arizona->mclk[ARIZONA_MCLK2]); @@ -67,8 +69,6 @@ int arizona_clk32k_enable(struct arizona *arizona) ARIZONA_CLK_32K_ENA); } -err_pm: - pm_runtime_put_sync(arizona->dev); err_ref: if (ret != 0) arizona->clk32k_ref--; -- cgit v1.2.3 From b04e68d16605dcde1c21b5df5f86a5372e53ae97 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Mon, 27 Aug 2018 14:51:15 +0100 Subject: mfd: madera: Don't use regmap_read_poll_timeout to poll for BOOT_DONE While polling for BOOT_DONE the chip could NAK a read because it is still booting, which would terminate the regmap_read_poll_timeout() with an error. Instead implement a polling loop that ignores read errors so we always poll until the chip signals boot or the loop times out. Signed-off-by: Richard Fitzgerald Signed-off-by: Lee Jones --- drivers/mfd/madera-core.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/madera-core.c b/drivers/mfd/madera-core.c index 8cfea969b060..440030cecbbd 100644 --- a/drivers/mfd/madera-core.c +++ b/drivers/mfd/madera-core.c @@ -132,32 +132,39 @@ const char *madera_name_from_type(enum madera_type type) } EXPORT_SYMBOL_GPL(madera_name_from_type); -#define MADERA_BOOT_POLL_MAX_INTERVAL_US 5000 -#define MADERA_BOOT_POLL_TIMEOUT_US 25000 +#define MADERA_BOOT_POLL_INTERVAL_USEC 5000 +#define MADERA_BOOT_POLL_TIMEOUT_USEC 25000 static int madera_wait_for_boot(struct madera *madera) { + ktime_t timeout; unsigned int val; - int ret; + int ret = 0; /* * 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. + * The chip could NAK a read request while it is booting so ignore + * errors from regmap_read. */ - ret = regmap_read_poll_timeout(madera->regmap, - MADERA_IRQ1_RAW_STATUS_1, - val, - (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); + timeout = ktime_add_us(ktime_get(), MADERA_BOOT_POLL_TIMEOUT_USEC); + regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_1, &val); + while (!(val & MADERA_BOOT_DONE_STS1) && + !ktime_after(ktime_get(), timeout)) { + usleep_range(MADERA_BOOT_POLL_INTERVAL_USEC / 2, + MADERA_BOOT_POLL_INTERVAL_USEC); + regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_1, &val); + }; + + if (!(val & MADERA_BOOT_DONE_STS1)) { + dev_err(madera->dev, "Polling BOOT_DONE_STS timed out\n"); + ret = -ETIMEDOUT; + } /* * BOOT_DONE defaults to unmasked on boot so we must ack it. - * Do this unconditionally to avoid interrupt storms. + * Do this even after a timeout to avoid interrupt storms. */ regmap_write(madera->regmap, MADERA_IRQ1_STATUS_1, MADERA_BOOT_DONE_EINT1); -- cgit v1.2.3 From 75a11072c462e69b7b2392b181ec1752a05f620d Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 27 Aug 2018 20:52:31 -0500 Subject: mfd: max77620: Convert to using %pOFn instead of device_node.name In preparation to remove the node name pointer from struct device_node, convert printf users to use the %pOFn format specifier. Signed-off-by: Rob Herring Signed-off-by: Lee Jones --- drivers/mfd/max77620.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c index b1700b5fa640..d8217366ed36 100644 --- a/drivers/mfd/max77620.c +++ b/drivers/mfd/max77620.c @@ -285,7 +285,7 @@ static int max77620_config_fps(struct max77620_chip *chip, } if (fps_id == MAX77620_FPS_COUNT) { - dev_err(dev, "FPS node name %s is not valid\n", fps_np->name); + dev_err(dev, "FPS node name %pOFn is not valid\n", fps_np); return -EINVAL; } -- cgit v1.2.3 From 55143439b7b501882bea9d95a54adfe00ffc79a3 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 28 Aug 2018 17:02:40 -0300 Subject: mfd: mc13xxx-core: Fix PMIC shutdown when reading ADC values When trying to read any MC13892 ADC channel on a imx51-babbage board: The MC13892 PMIC shutdowns completely. After debugging this issue and comparing the MC13892 and MC13783 initializations done in the vendor kernel, it was noticed that the CHRGRAWDIV bit of the ADC0 register was not being set. This bit is set by default after power on, but the driver was clearing it. After setting this bit it is possible to read the ADC values correctly. Signed-off-by: Fabio Estevam Tested-by: Chris Healy Signed-off-by: Lee Jones --- drivers/mfd/mc13xxx-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c index c63e331738c1..f475e848252f 100644 --- a/drivers/mfd/mc13xxx-core.c +++ b/drivers/mfd/mc13xxx-core.c @@ -276,7 +276,8 @@ int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode, mc13xxx_reg_read(mc13xxx, MC13XXX_ADC0, &old_adc0); - adc0 = MC13XXX_ADC0_ADINC1 | MC13XXX_ADC0_ADINC2; + adc0 = MC13XXX_ADC0_ADINC1 | MC13XXX_ADC0_ADINC2 | + MC13XXX_ADC0_CHRGRAWDIV; adc1 = MC13XXX_ADC1_ADEN | MC13XXX_ADC1_ADTRIGIGN | MC13XXX_ADC1_ASC; /* -- cgit v1.2.3 From 86f955d29ff83e15da62ad5de53a5480309da078 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Wed, 29 Aug 2018 11:31:04 +0200 Subject: mfd: motorola-cpcap: Add audio-codec support Add support for the audio-codec node by converting from devm_of_platform_populate() to devm_mfd_add_devices(). Tested-by: Pavel Machek Acked-by: Tony Lindgren Signed-off-by: Sebastian Reichel Signed-off-by: Pavel Machek Signed-off-by: Lee Jones --- drivers/mfd/motorola-cpcap.c | 51 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/motorola-cpcap.c b/drivers/mfd/motorola-cpcap.c index 5276911caaec..20d9692640e1 100644 --- a/drivers/mfd/motorola-cpcap.c +++ b/drivers/mfd/motorola-cpcap.c @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -216,6 +217,53 @@ static const struct regmap_config cpcap_regmap_config = { .val_format_endian = REGMAP_ENDIAN_LITTLE, }; +static const struct mfd_cell cpcap_mfd_devices[] = { + { + .name = "cpcap_adc", + .of_compatible = "motorola,mapphone-cpcap-adc", + }, { + .name = "cpcap_battery", + .of_compatible = "motorola,cpcap-battery", + }, { + .name = "cpcap-charger", + .of_compatible = "motorola,mapphone-cpcap-charger", + }, { + .name = "cpcap-regulator", + .of_compatible = "motorola,mapphone-cpcap-regulator", + }, { + .name = "cpcap-rtc", + .of_compatible = "motorola,cpcap-rtc", + }, { + .name = "cpcap-pwrbutton", + .of_compatible = "motorola,cpcap-pwrbutton", + }, { + .name = "cpcap-usb-phy", + .of_compatible = "motorola,mapphone-cpcap-usb-phy", + }, { + .name = "cpcap-led", + .id = 0, + .of_compatible = "motorola,cpcap-led-red", + }, { + .name = "cpcap-led", + .id = 1, + .of_compatible = "motorola,cpcap-led-green", + }, { + .name = "cpcap-led", + .id = 2, + .of_compatible = "motorola,cpcap-led-blue", + }, { + .name = "cpcap-led", + .id = 3, + .of_compatible = "motorola,cpcap-led-adl", + }, { + .name = "cpcap-led", + .id = 4, + .of_compatible = "motorola,cpcap-led-cp", + }, { + .name = "cpcap-codec", + } +}; + static int cpcap_probe(struct spi_device *spi) { const struct of_device_id *match; @@ -260,7 +308,8 @@ static int cpcap_probe(struct spi_device *spi) if (ret) return ret; - return devm_of_platform_populate(&cpcap->spi->dev); + return devm_mfd_add_devices(&spi->dev, 0, cpcap_mfd_devices, + ARRAY_SIZE(cpcap_mfd_devices), NULL, 0, NULL); } static struct spi_driver cpcap_driver = { -- cgit v1.2.3 From 95d617b4d66cd783f643cb763c096c2ce5f6b490 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 30 Aug 2018 19:52:49 +0300 Subject: mfd: intel_msic: Use DEFINE_RES_IRQ() macro Instead of open coding each data structure with IRQ resources, use dedicated macro. In one case use DEFINE_RES_IRQ_NAMED() and DEFINE_RES_MEM_NAMED(). No functional change intended. Signed-off-by: Andy Shevchenko Reviewed-by: Mika Westerberg Signed-off-by: Lee Jones --- drivers/mfd/intel_msic.c | 44 ++++++++++---------------------------------- 1 file changed, 10 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c index 2017446c5b4b..441de7b3d231 100644 --- a/drivers/mfd/intel_msic.c +++ b/drivers/mfd/intel_msic.c @@ -54,68 +54,44 @@ struct intel_msic { }; static struct resource msic_touch_resources[] = { - { - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ(0), }; static struct resource msic_adc_resources[] = { - { - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ(0), }; static struct resource msic_battery_resources[] = { - { - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ(0), }; static struct resource msic_gpio_resources[] = { - { - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ(0), }; static struct resource msic_audio_resources[] = { - { - .name = "IRQ", - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(0, "IRQ"), /* * We will pass IRQ_BASE to the driver now but this can be removed * when/if the driver starts to use intel_msic_irq_read(). */ - { - .name = "IRQ_BASE", - .flags = IORESOURCE_MEM, - .start = MSIC_IRQ_STATUS_ACCDET, - .end = MSIC_IRQ_STATUS_ACCDET, - }, + DEFINE_RES_MEM_NAMED(MSIC_IRQ_STATUS_ACCDET, 1, "IRQ_BASE"), }; static struct resource msic_hdmi_resources[] = { - { - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ(0), }; static struct resource msic_thermal_resources[] = { - { - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ(0), }; static struct resource msic_power_btn_resources[] = { - { - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ(0), }; static struct resource msic_ocd_resources[] = { - { - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ(0), }; /* -- cgit v1.2.3 From 0ce8ea71fae006fce5ddd7fc6f22d1a6c72375a6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 30 Aug 2018 19:52:50 +0300 Subject: mfd: intel_soc_pmic_crc: Use DEFINE_RES_IRQ_NAMED() macro Instead of open coding each data structure with IRQ resources, use dedicated macro. No functional change intended. Signed-off-by: Andy Shevchenko Reviewed-by: Mika Westerberg Signed-off-by: Lee Jones --- drivers/mfd/intel_soc_pmic_crc.c | 35 +++++------------------------------ 1 file changed, 5 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/intel_soc_pmic_crc.c b/drivers/mfd/intel_soc_pmic_crc.c index 6d19a6d0fb97..de3f31266c57 100644 --- a/drivers/mfd/intel_soc_pmic_crc.c +++ b/drivers/mfd/intel_soc_pmic_crc.c @@ -36,48 +36,23 @@ #define CRYSTAL_COVE_IRQ_VHDMIOCP 6 static struct resource gpio_resources[] = { - { - .name = "GPIO", - .start = CRYSTAL_COVE_IRQ_GPIO, - .end = CRYSTAL_COVE_IRQ_GPIO, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(CRYSTAL_COVE_IRQ_GPIO, "GPIO"), }; static struct resource pwrsrc_resources[] = { - { - .name = "PWRSRC", - .start = CRYSTAL_COVE_IRQ_PWRSRC, - .end = CRYSTAL_COVE_IRQ_PWRSRC, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(CRYSTAL_COVE_IRQ_PWRSRC, "PWRSRC"), }; static struct resource adc_resources[] = { - { - .name = "ADC", - .start = CRYSTAL_COVE_IRQ_ADC, - .end = CRYSTAL_COVE_IRQ_ADC, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(CRYSTAL_COVE_IRQ_ADC, "ADC"), }; static struct resource thermal_resources[] = { - { - .name = "THERMAL", - .start = CRYSTAL_COVE_IRQ_THRM, - .end = CRYSTAL_COVE_IRQ_THRM, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(CRYSTAL_COVE_IRQ_THRM, "THERMAL"), }; static struct resource bcu_resources[] = { - { - .name = "BCU", - .start = CRYSTAL_COVE_IRQ_BCU, - .end = CRYSTAL_COVE_IRQ_BCU, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(CRYSTAL_COVE_IRQ_BCU, "BCU"), }; static struct mfd_cell crystal_cove_byt_dev[] = { -- cgit v1.2.3 From 8bd2d03e54bbe2c75802c81f5635ebb4c36f7a2c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 30 Aug 2018 19:52:51 +0300 Subject: mfd: intel_soc_pmic_crc: Use REGMAP_IRQ_REG() macro Instead of open coding each data structure with regmap IRQresources, use dedicated macro. No functional change intended. Signed-off-by: Andy Shevchenko Reviewed-by: Mika Westerberg Signed-off-by: Lee Jones --- drivers/mfd/intel_soc_pmic_crc.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/intel_soc_pmic_crc.c b/drivers/mfd/intel_soc_pmic_crc.c index de3f31266c57..d33a0cff8cbd 100644 --- a/drivers/mfd/intel_soc_pmic_crc.c +++ b/drivers/mfd/intel_soc_pmic_crc.c @@ -109,27 +109,13 @@ static const struct regmap_config crystal_cove_regmap_config = { }; static const struct regmap_irq crystal_cove_irqs[] = { - [CRYSTAL_COVE_IRQ_PWRSRC] = { - .mask = BIT(CRYSTAL_COVE_IRQ_PWRSRC), - }, - [CRYSTAL_COVE_IRQ_THRM] = { - .mask = BIT(CRYSTAL_COVE_IRQ_THRM), - }, - [CRYSTAL_COVE_IRQ_BCU] = { - .mask = BIT(CRYSTAL_COVE_IRQ_BCU), - }, - [CRYSTAL_COVE_IRQ_ADC] = { - .mask = BIT(CRYSTAL_COVE_IRQ_ADC), - }, - [CRYSTAL_COVE_IRQ_CHGR] = { - .mask = BIT(CRYSTAL_COVE_IRQ_CHGR), - }, - [CRYSTAL_COVE_IRQ_GPIO] = { - .mask = BIT(CRYSTAL_COVE_IRQ_GPIO), - }, - [CRYSTAL_COVE_IRQ_VHDMIOCP] = { - .mask = BIT(CRYSTAL_COVE_IRQ_VHDMIOCP), - }, + REGMAP_IRQ_REG(CRYSTAL_COVE_IRQ_PWRSRC, 0, BIT(CRYSTAL_COVE_IRQ_PWRSRC)), + REGMAP_IRQ_REG(CRYSTAL_COVE_IRQ_THRM, 0, BIT(CRYSTAL_COVE_IRQ_THRM)), + REGMAP_IRQ_REG(CRYSTAL_COVE_IRQ_BCU, 0, BIT(CRYSTAL_COVE_IRQ_BCU)), + REGMAP_IRQ_REG(CRYSTAL_COVE_IRQ_ADC, 0, BIT(CRYSTAL_COVE_IRQ_ADC)), + REGMAP_IRQ_REG(CRYSTAL_COVE_IRQ_CHGR, 0, BIT(CRYSTAL_COVE_IRQ_CHGR)), + REGMAP_IRQ_REG(CRYSTAL_COVE_IRQ_GPIO, 0, BIT(CRYSTAL_COVE_IRQ_GPIO)), + REGMAP_IRQ_REG(CRYSTAL_COVE_IRQ_VHDMIOCP, 0, BIT(CRYSTAL_COVE_IRQ_VHDMIOCP)), }; static const struct regmap_irq_chip crystal_cove_irq_chip = { -- cgit v1.2.3 From 9f8ddee1dab836ca758ca8fc555ab5a3aaa5d3fd Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 30 Aug 2018 19:52:52 +0300 Subject: mfd: intel_soc_pmic_bxtwc: Chain power button IRQs as well Power button IRQ actually has a second level of interrupts to distinguish between UI and POWER buttons. Moreover, current implementation looks awkward in approach to handle second level IRQs by first level related IRQ chip. To address above issues, split power button IRQ to be chained as well. Signed-off-by: Andy Shevchenko Reviewed-by: Mika Westerberg Signed-off-by: Lee Jones --- drivers/mfd/intel_soc_pmic_bxtwc.c | 41 ++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c b/drivers/mfd/intel_soc_pmic_bxtwc.c index 15bc052704a6..9ca1f8c015de 100644 --- a/drivers/mfd/intel_soc_pmic_bxtwc.c +++ b/drivers/mfd/intel_soc_pmic_bxtwc.c @@ -31,8 +31,8 @@ /* Interrupt Status Registers */ #define BXTWC_IRQLVL1 0x4E02 -#define BXTWC_PWRBTNIRQ 0x4E03 +#define BXTWC_PWRBTNIRQ 0x4E03 #define BXTWC_THRM0IRQ 0x4E04 #define BXTWC_THRM1IRQ 0x4E05 #define BXTWC_THRM2IRQ 0x4E06 @@ -47,10 +47,9 @@ /* Interrupt MASK Registers */ #define BXTWC_MIRQLVL1 0x4E0E -#define BXTWC_MPWRTNIRQ 0x4E0F - #define BXTWC_MIRQLVL1_MCHGR BIT(5) +#define BXTWC_MPWRBTNIRQ 0x4E0F #define BXTWC_MTHRM0IRQ 0x4E12 #define BXTWC_MTHRM1IRQ 0x4E13 #define BXTWC_MTHRM2IRQ 0x4E14 @@ -66,9 +65,7 @@ /* Whiskey Cove PMIC share same ACPI ID between different platforms */ #define BROXTON_PMIC_WC_HRV 4 -/* Manage in two IRQ chips since mask registers are not consecutive */ enum bxtwc_irqs { - /* Level 1 */ BXTWC_PWRBTN_LVL1_IRQ = 0, BXTWC_TMU_LVL1_IRQ, BXTWC_THRM_LVL1_IRQ, @@ -77,9 +74,11 @@ enum bxtwc_irqs { BXTWC_CHGR_LVL1_IRQ, BXTWC_GPIO_LVL1_IRQ, BXTWC_CRIT_LVL1_IRQ, +}; - /* Level 2 */ - BXTWC_PWRBTN_IRQ, +enum bxtwc_irqs_pwrbtn { + BXTWC_PWRBTN_IRQ = 0, + BXTWC_UIBTN_IRQ, }; enum bxtwc_irqs_bcu { @@ -113,7 +112,10 @@ static const struct regmap_irq bxtwc_regmap_irqs[] = { REGMAP_IRQ_REG(BXTWC_CHGR_LVL1_IRQ, 0, BIT(5)), REGMAP_IRQ_REG(BXTWC_GPIO_LVL1_IRQ, 0, BIT(6)), REGMAP_IRQ_REG(BXTWC_CRIT_LVL1_IRQ, 0, BIT(7)), - REGMAP_IRQ_REG(BXTWC_PWRBTN_IRQ, 1, 0x03), +}; + +static const struct regmap_irq bxtwc_regmap_irqs_pwrbtn[] = { + REGMAP_IRQ_REG(BXTWC_PWRBTN_IRQ, 0, 0x01), }; static const struct regmap_irq bxtwc_regmap_irqs_bcu[] = { @@ -125,7 +127,7 @@ static const struct regmap_irq bxtwc_regmap_irqs_adc[] = { }; static const struct regmap_irq bxtwc_regmap_irqs_chgr[] = { - REGMAP_IRQ_REG(BXTWC_USBC_IRQ, 0, BIT(5)), + REGMAP_IRQ_REG(BXTWC_USBC_IRQ, 0, 0x20), REGMAP_IRQ_REG(BXTWC_CHGR0_IRQ, 0, 0x1f), REGMAP_IRQ_REG(BXTWC_CHGR1_IRQ, 1, 0x1f), }; @@ -144,7 +146,16 @@ static struct regmap_irq_chip bxtwc_regmap_irq_chip = { .mask_base = BXTWC_MIRQLVL1, .irqs = bxtwc_regmap_irqs, .num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs), - .num_regs = 2, + .num_regs = 1, +}; + +static struct regmap_irq_chip bxtwc_regmap_irq_chip_pwrbtn = { + .name = "bxtwc_irq_chip_pwrbtn", + .status_base = BXTWC_PWRBTNIRQ, + .mask_base = BXTWC_MPWRBTNIRQ, + .irqs = bxtwc_regmap_irqs_pwrbtn, + .num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_pwrbtn), + .num_regs = 1, }; static struct regmap_irq_chip bxtwc_regmap_irq_chip_tmu = { @@ -472,6 +483,16 @@ static int bxtwc_probe(struct platform_device *pdev) return ret; } + ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data, + BXTWC_PWRBTN_LVL1_IRQ, + IRQF_ONESHOT, + &bxtwc_regmap_irq_chip_pwrbtn, + &pmic->irq_chip_data_pwrbtn); + if (ret) { + dev_err(&pdev->dev, "Failed to add PWRBTN IRQ chip\n"); + return ret; + } + ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data, BXTWC_TMU_LVL1_IRQ, IRQF_ONESHOT, -- cgit v1.2.3 From 51eeee8e4e41b110b1afa374a9e7a532f4fb3e24 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 30 Aug 2018 19:52:53 +0300 Subject: mfd: Sort headers alphabetically for Intel PMIC drivers Sort headers alphabetically for better maintenance. No functional change. Signed-off-by: Andy Shevchenko Reviewed-by: Mika Westerberg Signed-off-by: Lee Jones --- drivers/mfd/intel_soc_pmic_bxtwc.c | 5 +++-- drivers/mfd/intel_soc_pmic_core.c | 13 +++++++------ drivers/mfd/intel_soc_pmic_crc.c | 3 ++- 3 files changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c b/drivers/mfd/intel_soc_pmic_bxtwc.c index 9ca1f8c015de..c878724497a9 100644 --- a/drivers/mfd/intel_soc_pmic_bxtwc.c +++ b/drivers/mfd/intel_soc_pmic_bxtwc.c @@ -13,15 +13,16 @@ * more details. */ -#include #include -#include #include +#include #include #include #include #include #include +#include + #include /* PMIC device registers */ diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c index 274306d98ac1..170d5ed16a3b 100644 --- a/drivers/mfd/intel_soc_pmic_core.c +++ b/drivers/mfd/intel_soc_pmic_core.c @@ -16,16 +16,17 @@ * Author: Zhu, Lejun */ -#include -#include +#include +#include +#include #include #include -#include -#include -#include +#include +#include #include -#include #include +#include + #include "intel_soc_pmic_core.h" /* Crystal Cove PMIC shares same ACPI ID between different platforms */ diff --git a/drivers/mfd/intel_soc_pmic_crc.c b/drivers/mfd/intel_soc_pmic_crc.c index d33a0cff8cbd..5ac6f3710294 100644 --- a/drivers/mfd/intel_soc_pmic_crc.c +++ b/drivers/mfd/intel_soc_pmic_crc.c @@ -16,10 +16,11 @@ * Author: Zhu, Lejun */ -#include #include #include +#include #include + #include "intel_soc_pmic_core.h" #define CRYSTAL_COVE_MAX_REGISTER 0xC6 -- cgit v1.2.3 From 26c7e05a69d3843abb0e5389e7f538cd175c0f09 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 30 Aug 2018 19:52:54 +0300 Subject: mfd: Convert Intel PMIC drivers to use SPDX identifier 1;5201;0c Reduce size of duplicated comments by switching to use SPDX identifier. No functional change. Signed-off-by: Andy Shevchenko Reviewed-by: Mika Westerberg Signed-off-by: Lee Jones --- drivers/mfd/intel_msic.c | 5 +---- drivers/mfd/intel_soc_pmic_bxtwc.c | 10 +--------- drivers/mfd/intel_soc_pmic_chtdc_ti.c | 5 +---- drivers/mfd/intel_soc_pmic_chtwc.c | 5 +---- drivers/mfd/intel_soc_pmic_core.c | 12 ++---------- drivers/mfd/intel_soc_pmic_core.h | 12 ++---------- drivers/mfd/intel_soc_pmic_crc.c | 12 ++---------- 7 files changed, 10 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c index 441de7b3d231..bb24c2a07900 100644 --- a/drivers/mfd/intel_msic.c +++ b/drivers/mfd/intel_msic.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Driver for Intel MSIC * * Copyright (C) 2011, Intel Corporation * Author: Mika Westerberg - * - * 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. */ #include diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c b/drivers/mfd/intel_soc_pmic_bxtwc.c index c878724497a9..6310c3bdb991 100644 --- a/drivers/mfd/intel_soc_pmic_bxtwc.c +++ b/drivers/mfd/intel_soc_pmic_bxtwc.c @@ -1,16 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * MFD core driver for Intel Broxton Whiskey Cove PMIC * * Copyright (C) 2015 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. */ #include diff --git a/drivers/mfd/intel_soc_pmic_chtdc_ti.c b/drivers/mfd/intel_soc_pmic_chtdc_ti.c index 861277c6580a..64b5c3cc30e7 100644 --- a/drivers/mfd/intel_soc_pmic_chtdc_ti.c +++ b/drivers/mfd/intel_soc_pmic_chtdc_ti.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Device access for Dollar Cove TI PMIC * @@ -6,10 +7,6 @@ * * Cleanup and forward-ported * Copyright (c) 2017 Takashi Iwai - * - * 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. */ #include diff --git a/drivers/mfd/intel_soc_pmic_chtwc.c b/drivers/mfd/intel_soc_pmic_chtwc.c index b35da01d5bcf..64a3aece9c5e 100644 --- a/drivers/mfd/intel_soc_pmic_chtwc.c +++ b/drivers/mfd/intel_soc_pmic_chtwc.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * MFD core driver for Intel Cherrytrail Whiskey Cove PMIC * @@ -5,10 +6,6 @@ * * Based on various non upstream patches to support the CHT Whiskey Cove PMIC: * Copyright (C) 2013-2015 Intel Corporation. All rights reserved. - * - * 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. */ #include diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c index 170d5ed16a3b..c9f35378d391 100644 --- a/drivers/mfd/intel_soc_pmic_core.c +++ b/drivers/mfd/intel_soc_pmic_core.c @@ -1,17 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * intel_soc_pmic_core.c - Intel SoC PMIC MFD Driver + * Intel SoC PMIC MFD Driver * * Copyright (C) 2013, 2014 Intel Corporation. All rights reserved. * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * * Author: Yang, Bin * Author: Zhu, Lejun */ diff --git a/drivers/mfd/intel_soc_pmic_core.h b/drivers/mfd/intel_soc_pmic_core.h index 90a1416d4dac..d490685845eb 100644 --- a/drivers/mfd/intel_soc_pmic_core.h +++ b/drivers/mfd/intel_soc_pmic_core.h @@ -1,17 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* - * intel_soc_pmic_core.h - Intel SoC PMIC MFD Driver + * Intel SoC PMIC MFD Driver * * Copyright (C) 2012-2014 Intel Corporation. All rights reserved. * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * * Author: Yang, Bin * Author: Zhu, Lejun */ diff --git a/drivers/mfd/intel_soc_pmic_crc.c b/drivers/mfd/intel_soc_pmic_crc.c index 5ac6f3710294..b6ab72fa0569 100644 --- a/drivers/mfd/intel_soc_pmic_crc.c +++ b/drivers/mfd/intel_soc_pmic_crc.c @@ -1,17 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * intel_soc_pmic_crc.c - Device access for Crystal Cove PMIC + * Device access for Crystal Cove PMIC * * Copyright (C) 2013, 2014 Intel Corporation. All rights reserved. * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * * Author: Yang, Bin * Author: Zhu, Lejun */ -- cgit v1.2.3 From 8e27a5638ab5c1b5434a0c22bc43ec6c3f7f5b6b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 4 Sep 2018 15:15:53 +0100 Subject: mfd: arizona: Make array mclk_name static, shrinks object size Don't populate the array mclk_name on the stack but instead make it static. Makes the object code smaller by 23 bytes: Before: text data bss dec hex filename 38050 11604 64 49718 c236 linux/drivers/mfd/arizona-core.o After: text data bss dec hex filename 38027 11604 64 49695 c21f linux/drivers/mfd/arizona-core.o (gcc version 8.2.0 x86_64) Signed-off-by: Colin Ian King Acked-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/arizona-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 057906e3c16e..27b61639cdc7 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -990,7 +990,7 @@ static const struct mfd_cell wm8998_devs[] = { int arizona_dev_init(struct arizona *arizona) { - const char * const mclk_name[] = { "mclk1", "mclk2" }; + static const char * const mclk_name[] = { "mclk1", "mclk2" }; struct device *dev = arizona->dev; const char *type_name = NULL; unsigned int reg, val; -- cgit v1.2.3 From efddff27c886e729a7f84a7205bd84d7d4af7336 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 5 Sep 2018 13:54:07 +0200 Subject: mfd: max8997: Enale irq-wakeup unconditionally IRQ wake up support for MAX8997 driver was initially configured by respective property in pdata. However, after the driver conversion to device-tree, setting it was left as 'todo'. Nowadays most of other PMIC MFD drivers initialized from device-tree assume that they can be an irq wakeup source, so enable it also for MAX8997. This fixes support for wakeup from MAX8997 RTC alarm. Signed-off-by: Marek Szyprowski Reviewed-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/max8997.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index 8dbae31911a1..f99e8da99782 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -139,12 +139,6 @@ static struct max8997_platform_data *max8997_i2c_parse_dt_pdata( pd->ono = irq_of_parse_and_map(dev->of_node, 1); - /* - * ToDo: the 'wakeup' member in the platform data is more of a linux - * specfic information. Hence, there is no binding for that yet and - * not parsed here. - */ - return pd; } @@ -232,7 +226,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c, */ /* MAX8997 has a power button input. */ - device_init_wakeup(max8997->dev, pdata->wakeup); + device_init_wakeup(max8997->dev, true); return ret; -- cgit v1.2.3 From c1aaaa1cb7c82fe53463fba4928405fddcc4ea27 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 5 Sep 2018 16:36:06 +0200 Subject: mfd: max8997: Disable interrupt handling for suspend/resume cycle Disable IRQs during suspend/resume cycle to ensure handling of wakeup interrupts (i.e. RTC wake alarm) after max8997_resume(). This way it can be properly handled when I2C bus is finally available. This pattern is also used in other MAX PMIC MFD drivers. Signed-off-by: Marek Szyprowski Reviewed-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/max8997.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index f99e8da99782..8c06c09e36d1 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -448,6 +448,7 @@ static int max8997_suspend(struct device *dev) struct i2c_client *i2c = to_i2c_client(dev); struct max8997_dev *max8997 = i2c_get_clientdata(i2c); + disable_irq(max8997->irq); if (device_may_wakeup(dev)) irq_set_irq_wake(max8997->irq, 1); return 0; @@ -460,6 +461,7 @@ static int max8997_resume(struct device *dev) if (device_may_wakeup(dev)) irq_set_irq_wake(max8997->irq, 0); + enable_irq(max8997->irq); return max8997_irq_resume(max8997); } -- cgit v1.2.3 From 5b6850fa90c581f3743bb369861074d23d0e9f3c Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Wed, 29 Aug 2018 11:31:09 +0200 Subject: mfd: ti-lmu: constify mfd_cell tables Add const attribute to all mfd_cell structures. Signed-off-by: Sebastian Reichel Signed-off-by: Pavel Machek Signed-off-by: Lee Jones --- drivers/mfd/ti-lmu.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/ti-lmu.c b/drivers/mfd/ti-lmu.c index cfb411cde51c..990437e5ed0a 100644 --- a/drivers/mfd/ti-lmu.c +++ b/drivers/mfd/ti-lmu.c @@ -25,7 +25,7 @@ #include struct ti_lmu_data { - struct mfd_cell *cells; + const struct mfd_cell *cells; int num_cells; unsigned int max_register; }; @@ -63,7 +63,7 @@ static void ti_lmu_disable_hw(struct ti_lmu *lmu) gpio_set_value(lmu->en_gpio, 0); } -static struct mfd_cell lm3532_devices[] = { +static const struct mfd_cell lm3532_devices[] = { { .name = "ti-lmu-backlight", .id = LM3532, @@ -78,7 +78,7 @@ static struct mfd_cell lm3532_devices[] = { .of_compatible = "ti,lm363x-regulator", \ } \ -static struct mfd_cell lm3631_devices[] = { +static const struct mfd_cell lm3631_devices[] = { LM363X_REGULATOR(LM3631_BOOST), LM363X_REGULATOR(LM3631_LDO_CONT), LM363X_REGULATOR(LM3631_LDO_OREF), @@ -91,7 +91,7 @@ static struct mfd_cell lm3631_devices[] = { }, }; -static struct mfd_cell lm3632_devices[] = { +static const struct mfd_cell lm3632_devices[] = { LM363X_REGULATOR(LM3632_BOOST), LM363X_REGULATOR(LM3632_LDO_POS), LM363X_REGULATOR(LM3632_LDO_NEG), @@ -102,7 +102,7 @@ static struct mfd_cell lm3632_devices[] = { }, }; -static struct mfd_cell lm3633_devices[] = { +static const struct mfd_cell lm3633_devices[] = { { .name = "ti-lmu-backlight", .id = LM3633, @@ -120,7 +120,7 @@ static struct mfd_cell lm3633_devices[] = { }, }; -static struct mfd_cell lm3695_devices[] = { +static const struct mfd_cell lm3695_devices[] = { { .name = "ti-lmu-backlight", .id = LM3695, @@ -128,7 +128,7 @@ static struct mfd_cell lm3695_devices[] = { }, }; -static struct mfd_cell lm3697_devices[] = { +static const struct mfd_cell lm3697_devices[] = { { .name = "ti-lmu-backlight", .id = LM3697, -- cgit v1.2.3 From 7a6a395b16c3fdcd2ede2b0ce4bf63f6dafc1fea Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Tue, 11 Sep 2018 23:01:33 +0200 Subject: mfd: ti-lmu: Switch to GPIOD Use new descriptor based API instead of the legacy one. Signed-off-by: Sebastian Reichel Signed-off-by: Pavel Machek Signed-off-by: Lee Jones --- drivers/mfd/ti-lmu.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/ti-lmu.c b/drivers/mfd/ti-lmu.c index 990437e5ed0a..e14cb9f41b44 100644 --- a/drivers/mfd/ti-lmu.c +++ b/drivers/mfd/ti-lmu.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include #include @@ -21,7 +21,6 @@ #include #include #include -#include #include struct ti_lmu_data { @@ -32,17 +31,8 @@ struct ti_lmu_data { static int ti_lmu_enable_hw(struct ti_lmu *lmu, enum ti_lmu_id id) { - int ret; - - if (gpio_is_valid(lmu->en_gpio)) { - ret = devm_gpio_request_one(lmu->dev, lmu->en_gpio, - GPIOF_OUT_INIT_HIGH, "lmu_hwen"); - if (ret) { - dev_err(lmu->dev, "Can not request enable GPIO: %d\n", - ret); - return ret; - } - } + if (lmu->en_gpio) + gpiod_set_value(lmu->en_gpio, 1); /* Delay about 1ms after HW enable pin control */ usleep_range(1000, 1500); @@ -59,8 +49,8 @@ static int ti_lmu_enable_hw(struct ti_lmu *lmu, enum ti_lmu_id id) static void ti_lmu_disable_hw(struct ti_lmu *lmu) { - if (gpio_is_valid(lmu->en_gpio)) - gpio_set_value(lmu->en_gpio, 0); + if (lmu->en_gpio) + gpiod_set_value(lmu->en_gpio, 0); } static const struct mfd_cell lm3532_devices[] = { @@ -204,7 +194,13 @@ static int ti_lmu_probe(struct i2c_client *cl, const struct i2c_device_id *id) return PTR_ERR(lmu->regmap); /* HW enable pin control and additional power up sequence if required */ - lmu->en_gpio = of_get_named_gpio(dev->of_node, "enable-gpios", 0); + lmu->en_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH); + if (IS_ERR(lmu->en_gpio)) { + ret = PTR_ERR(lmu->en_gpio); + dev_err(dev, "Can not request enable GPIO: %d\n", ret); + return ret; + } + ret = ti_lmu_enable_hw(lmu, id->driver_data); if (ret) return ret; -- cgit v1.2.3 From 7891d37509cca01f383e8349831ee0adc0724e77 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Tue, 11 Sep 2018 23:03:44 +0200 Subject: mfd: ti-lmu: Use managed resource for everything This replaces all remaining unmanaged resources with device managed ones, so that the remove function is no longer needed. This makes the code slightly shorter and fixes two problems: 1. The hardware is disabled after the child devices have been removed. Previously there was a potential race condition. 2. The hardware is disabled when mfd_add_devices fails during probe. Signed-off-by: Sebastian Reichel Signed-off-by: Pavel Machek Signed-off-by: Lee Jones --- drivers/mfd/ti-lmu.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/ti-lmu.c b/drivers/mfd/ti-lmu.c index e14cb9f41b44..2ee09d099832 100644 --- a/drivers/mfd/ti-lmu.c +++ b/drivers/mfd/ti-lmu.c @@ -47,8 +47,9 @@ static int ti_lmu_enable_hw(struct ti_lmu *lmu, enum ti_lmu_id id) return 0; } -static void ti_lmu_disable_hw(struct ti_lmu *lmu) +static void ti_lmu_disable_hw(void *data) { + struct ti_lmu *lmu = data; if (lmu->en_gpio) gpiod_set_value(lmu->en_gpio, 0); } @@ -205,6 +206,10 @@ static int ti_lmu_probe(struct i2c_client *cl, const struct i2c_device_id *id) if (ret) return ret; + ret = devm_add_action_or_reset(dev, ti_lmu_disable_hw, lmu); + if (ret) + return ret; + /* * Fault circuit(open/short) can be detected by ti-lmu-fault-monitor. * After fault detection is done, some devices should re-initialize @@ -214,17 +219,8 @@ static int ti_lmu_probe(struct i2c_client *cl, const struct i2c_device_id *id) i2c_set_clientdata(cl, lmu); - return mfd_add_devices(lmu->dev, 0, data->cells, - data->num_cells, NULL, 0, NULL); -} - -static int ti_lmu_remove(struct i2c_client *cl) -{ - struct ti_lmu *lmu = i2c_get_clientdata(cl); - - ti_lmu_disable_hw(lmu); - mfd_remove_devices(lmu->dev); - return 0; + return devm_mfd_add_devices(lmu->dev, 0, data->cells, + data->num_cells, NULL, 0, NULL); } static const struct i2c_device_id ti_lmu_ids[] = { @@ -240,7 +236,6 @@ MODULE_DEVICE_TABLE(i2c, ti_lmu_ids); static struct i2c_driver ti_lmu_driver = { .probe = ti_lmu_probe, - .remove = ti_lmu_remove, .driver = { .name = "ti-lmu", .of_match_table = ti_lmu_of_match, -- cgit v1.2.3 From 697894b9b8478764d59e1e1ae6caa4e9dd11eb51 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Tue, 11 Sep 2018 23:06:50 +0200 Subject: mfd: ti-lmu: Use of_device_get_match_data() helper Replace of_match_device() with of_device_get_match_data(), which slightly decreases lines of code and allows to move the DT table next to the I2C table. Signed-off-by: Sebastian Reichel Signed-off-by: Pavel Machek Signed-off-by: Lee Jones --- drivers/mfd/ti-lmu.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/ti-lmu.c b/drivers/mfd/ti-lmu.c index 2ee09d099832..37d0bdb291c3 100644 --- a/drivers/mfd/ti-lmu.c +++ b/drivers/mfd/ti-lmu.c @@ -148,34 +148,21 @@ TI_LMU_DATA(lm3633, LM3633_MAX_REG); TI_LMU_DATA(lm3695, LM3695_MAX_REG); TI_LMU_DATA(lm3697, LM3697_MAX_REG); -static const struct of_device_id ti_lmu_of_match[] = { - { .compatible = "ti,lm3532", .data = &lm3532_data }, - { .compatible = "ti,lm3631", .data = &lm3631_data }, - { .compatible = "ti,lm3632", .data = &lm3632_data }, - { .compatible = "ti,lm3633", .data = &lm3633_data }, - { .compatible = "ti,lm3695", .data = &lm3695_data }, - { .compatible = "ti,lm3697", .data = &lm3697_data }, - { } -}; -MODULE_DEVICE_TABLE(of, ti_lmu_of_match); - static int ti_lmu_probe(struct i2c_client *cl, const struct i2c_device_id *id) { struct device *dev = &cl->dev; - const struct of_device_id *match; const struct ti_lmu_data *data; struct regmap_config regmap_cfg; struct ti_lmu *lmu; int ret; - match = of_match_device(ti_lmu_of_match, dev); - if (!match) - return -ENODEV; /* * Get device specific data from of_match table. * This data is defined by using TI_LMU_DATA() macro. */ - data = (struct ti_lmu_data *)match->data; + data = of_device_get_match_data(dev); + if (!data) + return -ENODEV; lmu = devm_kzalloc(dev, sizeof(*lmu), GFP_KERNEL); if (!lmu) @@ -223,6 +210,17 @@ static int ti_lmu_probe(struct i2c_client *cl, const struct i2c_device_id *id) data->num_cells, NULL, 0, NULL); } +static const struct of_device_id ti_lmu_of_match[] = { + { .compatible = "ti,lm3532", .data = &lm3532_data }, + { .compatible = "ti,lm3631", .data = &lm3631_data }, + { .compatible = "ti,lm3632", .data = &lm3632_data }, + { .compatible = "ti,lm3633", .data = &lm3633_data }, + { .compatible = "ti,lm3695", .data = &lm3695_data }, + { .compatible = "ti,lm3697", .data = &lm3697_data }, + { } +}; +MODULE_DEVICE_TABLE(of, ti_lmu_of_match); + static const struct i2c_device_id ti_lmu_ids[] = { { "lm3532", LM3532 }, { "lm3631", LM3631 }, -- cgit v1.2.3 From 6eb357844373f833f085e63e6c8c026a61568c57 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Wed, 26 Sep 2018 20:33:17 -0700 Subject: mfd: cros_ec: Avoid unneeded internal declaration warning Clang warns: drivers/mfd/cros_ec_dev.c:509:40: warning: variable 'cros_ec_id' is not needed and will not be emitted [-Wunneeded-internal-declaration] static const struct platform_device_id cros_ec_id[] = { ^ 1 warning generated. Avoid this warning by adding it to the cros_ec_dev_driver definition under the id_table member like all other platform drivers. Signed-off-by: Nathan Chancellor Signed-off-by: Lee Jones --- drivers/mfd/cros_ec_dev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c index 999dac752bcc..8f9d6964173e 100644 --- a/drivers/mfd/cros_ec_dev.c +++ b/drivers/mfd/cros_ec_dev.c @@ -546,6 +546,7 @@ static struct platform_driver cros_ec_dev_driver = { .name = DRV_NAME, .pm = &cros_ec_dev_pm_ops, }, + .id_table = cros_ec_id, .probe = ec_device_probe, .remove = ec_device_remove, .shutdown = ec_device_shutdown, -- cgit v1.2.3