[PATCH v9 2/6] dt-bindings: add binding for atmel-usart in SPI mode
This patch moves the bindings for serial from serial/atmel-usart.txt to mfd/atmel-usart.txt and adds bindings for USART in SPI mode. Signed-off-by: Radu Pirea Reviewed-by: Rob Herring --- .../bindings/{serial => mfd}/atmel-usart.txt | 25 +-- include/dt-bindings/mfd/at91-usart.h | 17 + 2 files changed, 40 insertions(+), 2 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) create mode 100644 include/dt-bindings/mfd/at91-usart.h diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/mfd/atmel-usart.txt similarity index 76% rename from Documentation/devicetree/bindings/serial/atmel-usart.txt rename to Documentation/devicetree/bindings/mfd/atmel-usart.txt index 7c0d6b2f53e4..0348fef0f497 100644 --- a/Documentation/devicetree/bindings/serial/atmel-usart.txt +++ b/Documentation/devicetree/bindings/mfd/atmel-usart.txt @@ -1,6 +1,6 @@ * Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART) -Required properties: +Required properties for USART: - compatible: Should be "atmel,-usart" or "atmel,-dbgu" The compatible indicated will be the first SoC to support an additional mode or an USART new feature. @@ -11,7 +11,13 @@ Required properties: Required elements: "usart" - clocks: phandles to input clocks. -Optional properties: +Required properties for USART in SPI mode: +- #size-cells : Must be <0> +- #address-cells : Must be <1> +- cs-gpios: chipselects (internal cs not supported) +- atmel,usart-mode : Must be (found in dt-bindings/mfd/at91-usart.h) + +Optional properties in serial mode: - atmel,use-dma-rx: use of PDC or DMA for receiving data - atmel,use-dma-tx: use of PDC or DMA for transmitting data - {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD line respectively. @@ -62,3 +68,18 @@ Example: dma-names = "tx", "rx"; atmel,fifo-size = <32>; }; + +- SPI mode: + #include + + spi0: spi@f001c000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "atmel,at91rm9200-usart", "atmel,at91sam9260-usart"; + atmel,usart-mode = ; + reg = <0xf001c000 0x100>; + interrupts = <12 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&usart0_clk>; + clock-names = "usart"; + cs-gpios = <&pioB 3 0>; + }; diff --git a/include/dt-bindings/mfd/at91-usart.h b/include/dt-bindings/mfd/at91-usart.h new file mode 100644 index ..2de5bc312e1e --- /dev/null +++ b/include/dt-bindings/mfd/at91-usart.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * This header provides macros for AT91 USART DT bindings. + * + * Copyright (C) 2018 Microchip Technology + * + * Author: Radu Pirea + * + */ + +#ifndef __DT_BINDINGS_AT91_USART_H__ +#define __DT_BINDINGS_AT91_USART_H__ + +#define AT91_USART_MODE_SERIAL 0 +#define AT91_USART_MODE_SPI1 + +#endif /* __DT_BINDINGS_AT91_USART_H__ */ -- 2.17.1
[PATCH v9 0/6] Driver for at91 usart in spi mode
Hello, This is the second version of driver. I added a mfd driver which by default probes atmel_serial driver and if in dt is specified to probe the spi driver, then the spi-at91-usart driver will be probed. The compatible for atmel_serial is now the compatible for at91-usart mfd driver and compatilbe for atmel_serial driver was changed in order to keep the bindings for serial as they are. Changes in v9: - minor changes - rebased on top of broonie/for-4.19 Changes in v8: - fixed passing an empty mfd cell if "atmel,usart-mode" value is invalid Changes in v7: - synced up SPDIX license with module license - numbering of usart modes starts from 0 insteand of 1 Changes in v6: - removed unused compatible strings from serial and spi drivers Changes in v5: - fixed usage of stdout-path property with atmel_serial driver Changes in v4: - modified the spi driver to use cs gpio support form spi subsystem - fixed dma transfers for serial driver - squashed binding for spi and serial and moved them to mfd/atmel-usart.txt Changes in v3: - fixed spi slaves probing Changes in v2: - added at91-usart mfd driver - modified spi-at91-usart driver to work as mfd driver child - modified atmel_serial driver to work as mfd driver child Changes in v1: - added spi-at91-usart driver Radu Pirea (6): MAINTAINERS: add at91 usart mfd driver dt-bindings: add binding for atmel-usart in SPI mode mfd: at91-usart: added mfd driver for usart MAINTAINERS: add at91 usart spi driver spi: at91-usart: add driver for at91-usart as spi tty/serial: atmel: change the driver to work under at91-usart mfd .../bindings/{serial => mfd}/atmel-usart.txt | 25 +- MAINTAINERS | 16 + drivers/mfd/Kconfig | 9 + drivers/mfd/Makefile | 1 + drivers/mfd/at91-usart.c | 71 +++ drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 432 ++ drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 42 +- include/dt-bindings/mfd/at91-usart.h | 17 + 11 files changed, 607 insertions(+), 17 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) create mode 100644 drivers/mfd/at91-usart.c create mode 100644 drivers/spi/spi-at91-usart.c create mode 100644 include/dt-bindings/mfd/at91-usart.h -- 2.17.1
[PATCH v9 4/6] MAINTAINERS: add at91 usart spi driver
Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea --- MAINTAINERS | 7 +++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 7ac6e6af5292..f849cc4acbf6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9362,6 +9362,13 @@ F: drivers/mfd/at91-usart.c F: include/dt-bindings/mfd/at91-usart.h F: Documentation/devicetree/bindings/mfd/atmel-usart.txt +MICROCHIP AT91 USART SPI DRIVER +M: Radu Pirea +L: linux-...@vger.kernel.org +S: Supported +F: drivers/spi/spi-at91-usart.c +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.17.1
[PATCH v9 6/6] 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 Acked-by: Richard Genoud Reviewed-by: Andy Shevchenko --- drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 42 --- 2 files changed, 28 insertions(+), 15 deletions(-) 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", @@ -,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
[PATCH v9 3/6] mfd: at91-usart: added 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 Acked-by: Rob Herring Reviewed-by: Andy Shevchenko Acked-for-MFD-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 diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b860eb5aa194..a886672b960d 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 e9fd20dba18d..c7e66928abb9 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -184,6 +184,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 ..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"); -- 2.17.1
[PATCH v9 5/6] 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 --- drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 432 +++ 3 files changed, 442 insertions(+) create mode 100644 drivers/spi/spi-at91-usart.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index ad5d68e1dab7..02bb35057ccd 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -83,6 +83,15 @@ 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 HAS_DMA + depends on (ARCH_AT91 || COMPILE_TEST) + select 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 cb1f4378b87c..901ff606e6e5 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 ..0f92c02bf104 --- /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_BRGR0x20 +#define US_VERSION 0xFC + +#define US_CR_RSTRXBIT(2) +#define US_CR_RSTTXBIT(3) +#define US_CR_RXEN BIT(4) +#define US_CR_RXDISBIT(5) +#define US_CR_TXEN BIT(6) +#define US_CR_TXDISBIT(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_WRDBTBIT(20) +#define US_MR_LOOP BIT(15) + +#define US_IR_RXRDYBIT(0) +#define US_IR_TXRDYBIT(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 intcurrent_tx_remaining_bytes; + unsigned intcurrent_rx_remaining_bytes; + + u32 spi_clk; + u32 status; + + boolxfer_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_
[PATCH v9 1/6] MAINTAINERS: add at91 usart mfd driver
Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea --- MAINTAINERS | 9 + 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 9d5eeff51b5f..7ac6e6af5292 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9321,6 +9321,7 @@ M:Richard Genoud S: Maintained F: drivers/tty/serial/atmel_serial.c F: drivers/tty/serial/atmel_serial.h +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt MICROCHIP / ATMEL DMA DRIVER M: Ludovic Desroches @@ -9353,6 +9354,14 @@ S: Supported F: drivers/mtd/nand/raw/atmel/* F: Documentation/devicetree/bindings/mtd/atmel-nand.txt +MICROCHIP AT91 USART MFD DRIVER +M: Radu Pirea +L: linux-kernel@vger.kernel.org +S: Supported +F: drivers/mfd/at91-usart.c +F: include/dt-bindings/mfd/at91-usart.h +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.17.1
Re: [PATCH v11 0/6] Driver for at91 usart in spi mode
Hi Lee, I saw that the patches were not applied to your tree for this kernel version. After the discussion with Nicolas, I remember that you said that you will take the patches in your tree. I addressed Mark comments related to the last version of patches. Is there something that must be reworked in order to take the patches? On 7/13/18 7:47 PM, Radu Pirea - M19893 wrote: Hello, This is the second version of driver. I added a mfd driver which by default probes atmel_serial driver and if in dt is specified to probe the spi driver, then the spi-at91-usart driver will be probed. The compatible for atmel_serial is now the compatible for at91-usart mfd driver and compatilbe for atmel_serial driver was changed in order to keep the bindings for serial as they are. @Lee, could you take this patch series into your tree? I addressed all Mark remarks. Changes in v11: - removed "depends on HAS_DMA" from drivers/spi/Kconfig because the driver has no dma support - changed "selects MFD_AT91_USART" to "depends on MFD_AT91_USART" in drivers/spi/Kconfig - changed comment style in spi-at91-usart.c Changes in v10: -fixed kbuild test robot warning Changes in v9: - minor changes - rebased on top of broonie/for-4.19 Changes in v8: - fixed passing an empty mfd cell if "atmel,usart-mode" value is invalid Changes in v7: - synced up SPDIX license with module license - numbering of usart modes starts from 0 insteand of 1 Changes in v6: - removed unused compatible strings from serial and spi drivers Changes in v5: - fixed usage of stdout-path property with atmel_serial driver Changes in v4: - modified the spi driver to use cs gpio support form spi subsystem - fixed dma transfers for serial driver - squashed binding for spi and serial and moved them to mfd/atmel-usart.txt Changes in v3: - fixed spi slaves probing Changes in v2: - added at91-usart mfd driver - modified spi-at91-usart driver to work as mfd driver child - modified atmel_serial driver to work as mfd driver child Changes in v1: - added spi-at91-usart driver Radu Pirea (6): MAINTAINERS: add at91 usart mfd driver dt-bindings: add binding for atmel-usart in SPI mode mfd: at91-usart: added mfd driver for usart MAINTAINERS: add at91 usart spi driver spi: at91-usart: add driver for at91-usart as spi tty/serial: atmel: change the driver to work under at91-usart mfd .../bindings/{serial => mfd}/atmel-usart.txt | 25 +- MAINTAINERS | 16 + drivers/mfd/Kconfig | 9 + drivers/mfd/Makefile | 1 + drivers/mfd/at91-usart.c | 71 +++ drivers/spi/Kconfig | 8 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 432 ++ drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 42 +- include/dt-bindings/mfd/at91-usart.h | 17 + 11 files changed, 606 insertions(+), 17 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) create mode 100644 drivers/mfd/at91-usart.c create mode 100644 drivers/spi/spi-at91-usart.c create mode 100644 include/dt-bindings/mfd/at91-usart.h
Re: [PATCH v2 2/2] spi: add SPI controller driver for UniPhier SoC
On 07/26/2018 12:38 PM, Keiji Hayashibara wrote: Hello Andy, Thank you for your check! From: Andy Shevchenko [mailto:andy.shevche...@gmail.com] Sent: Thursday, July 26, 2018 5:46 PM To: Hayashibara, Keiji/ζε εδΊ Subject: Re: [PATCH v2 2/2] spi: add SPI controller driver for UniPhier SoC On Thu, Jul 26, 2018 at 10:09 AM, Keiji Hayashibara wrote: Add SPI controller driver implemented in Socionext UniPhier SoCs. UniPhier SoCs have two types SPI controllers; SCSSI supports a single channel, and MCSSI supports multiple channels. This driver supports SCSSI only. This controller has 32bit TX/RX FIFO with depth of eight entry, and supports the SPI master mode only. This commit is implemented in PIO transfer mode, not DMA transfer. Few style realted comments. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include Slightly better to keep them in order and put asm/* at the last. I see. I will modify this. +#define SSI_TIMEOUT2000/* ms */ SSI_TIMEOUT_MS ? +#define SSI_CTL0x0 Slightly better to keep same width for the addresses, like 0x00 here. +#define SSI_CKS0x4 +#define SSI_TXWDS 0x8 +#define SSI_RXWDS 0xc Ditto. I will modify about above. +static int uniphier_spi_set_baudrate(struct spi_device *spi, unsigned +int speed) { + struct uniphier_spi_priv *priv = spi_master_get_devdata(spi->master); + u32 val, ckrat; + + /* +* the supported rates are even numbers from 4 to 254. (4,6,8...254) +* round up as we look for equal or less speed +*/ + ckrat = DIV_ROUND_UP(clk_get_rate(priv->clk), speed); + ckrat = roundup(ckrat, 2); ckrat += ckrat & 1; ? It's simple. I will modify. + /* check if requested speed is too small */ + if (ckrat > SSI_MAX_CLK_DIVIDER) + return -EINVAL; So, does this critical? If set the value to SSI_MAX_CLK_DIVIDER, the clock frequency will be set high. I don't change it to high frequency, and it is daringly an error. On the other hand, when changing to low frequency, I will change it automatically. + + if (ckrat < SSI_MIN_CLK_DIVIDER) + ckrat = SSI_MIN_CLK_DIVIDER; In fact you don't need this checks. You already set in probe function this. master->max_speed_hz = DIV_ROUND_UP(clksrc, SSI_MIN_CLK_DIVIDER); master->min_speed_hz = DIV_ROUND_UP(clksrc, SSI_MAX_CLK_DIVIDER); The SPI core will check if transfer speed is higher than controller speed and if is, will set the transfer speed to master->max_speed_hz. In case of master->min_speed_hz, if transfer speed is lower than master->min_speed_hz __spi_validate(drivers/spi/spi.c) will return -EINVAL. clamp_val() / max() ? I will modify it to use max(). + val = readl(priv->base + SSI_CKS); + val &= ~SSI_CKS_CKRAT_MASK; + val |= ckrat & SSI_CKS_CKRAT_MASK; + writel(val, priv->base + SSI_CKS); + + return 0; +} + priv->irq = platform_get_irq(pdev, 0); + if (priv->irq < 0) { + dev_err(&pdev->dev, "failed to get IRQ\n"); + ret = -ENXIO; What's wrong with ret = priv->irq; ? I will modify it. + goto out_disable_clk; + } +static const struct of_device_id uniphier_spi_match[] = { + { .compatible = "socionext,uniphier-scssi", }, + { /* sentinel */ }, Slightly better without comma. OK. I will modify this. - Best Regards, Keiji Hayashibara +}; +MODULE_DEVICE_TABLE(of, uniphier_spi_match); -- With Best Regards, Andy Shevchenko -- To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v10 5/6] spi: at91-usart: add driver for at91-usart as spi
On 07/10/2018 09:15 PM, Mark Brown wrote: On Mon, Jun 25, 2018 at 08:22:29PM +0300, Radu Pirea wrote: This is mostly good, just a couple of small things: +config SPI_AT91_USART + tristate "Atmel USART Controller SPI driver" + depends on HAS_DMA + depends on (ARCH_AT91 || COMPILE_TEST) + select MFD_AT91_USART Why is this selecting rather than depending on the MFD like we normally do? Hi Mark, If I add depends instead of select, current defconfigs will be broken and the proper driver will not be selected. Like this, there is no required change in any defconfig. Selecting the serial or spi driver from menuconfig makes the MFD completely transparent. @@ -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 + */ Please use C++ comments for the whole block so it looks a bit more intentional. Ok. I will change it. Otherwise Reviwed-by: Mark Brown
[PATCH v11 1/6] MAINTAINERS: add at91 usart mfd driver
Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea Acked-by: Nicolas Ferre Acked-for-MFD-by: Lee Jones --- MAINTAINERS | 9 + 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 9d5eeff51b5f..7ac6e6af5292 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9321,6 +9321,7 @@ M:Richard Genoud S: Maintained F: drivers/tty/serial/atmel_serial.c F: drivers/tty/serial/atmel_serial.h +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt MICROCHIP / ATMEL DMA DRIVER M: Ludovic Desroches @@ -9353,6 +9354,14 @@ S: Supported F: drivers/mtd/nand/raw/atmel/* F: Documentation/devicetree/bindings/mtd/atmel-nand.txt +MICROCHIP AT91 USART MFD DRIVER +M: Radu Pirea +L: linux-kernel@vger.kernel.org +S: Supported +F: drivers/mfd/at91-usart.c +F: include/dt-bindings/mfd/at91-usart.h +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.18.0
[PATCH v11 3/6] mfd: at91-usart: added 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-for-MFD-by: Lee Jones Acked-by: Nicolas Ferre --- 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 diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b860eb5aa194..a886672b960d 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 e9fd20dba18d..c7e66928abb9 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -184,6 +184,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 ..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"); -- 2.18.0
[PATCH v11 4/6] MAINTAINERS: add at91 usart spi driver
Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea Acked-by: Nicolas Ferre --- MAINTAINERS | 7 +++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 7ac6e6af5292..f849cc4acbf6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9362,6 +9362,13 @@ F: drivers/mfd/at91-usart.c F: include/dt-bindings/mfd/at91-usart.h F: Documentation/devicetree/bindings/mfd/atmel-usart.txt +MICROCHIP AT91 USART SPI DRIVER +M: Radu Pirea +L: linux-...@vger.kernel.org +S: Supported +F: drivers/spi/spi-at91-usart.c +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.18.0
[PATCH v11 5/6] 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 --- 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 diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index ad5d68e1dab7..6d9e309fab67 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 cb1f4378b87c..901ff606e6e5 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 ..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_BRGR0x20 +#define US_VERSION 0xFC + +#define US_CR_RSTRXBIT(2) +#define US_CR_RSTTXBIT(3) +#define US_CR_RXEN BIT(4) +#define US_CR_RXDISBIT(5) +#define US_CR_TXEN BIT(6) +#define US_CR_TXDISBIT(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_WRDBTBIT(20) +#define US_MR_LOOP BIT(15) + +#define US_IR_RXRDYBIT(0) +#define US_IR_TXRDYBIT(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 intcurrent_tx_remaining_bytes; + unsigned intcurrent_rx_remaining_bytes; + + u32 spi_clk; + u32 status; + + boolxfer_failed; +}; + +static inline u32 at91_usart_spi_tx_ready(struct at91_usart_spi *aus) +{ + return aus->status & US_IR_TXRDY; +} + +st
[PATCH v11 0/6] Driver for at91 usart in spi mode
Hello, This is the second version of driver. I added a mfd driver which by default probes atmel_serial driver and if in dt is specified to probe the spi driver, then the spi-at91-usart driver will be probed. The compatible for atmel_serial is now the compatible for at91-usart mfd driver and compatilbe for atmel_serial driver was changed in order to keep the bindings for serial as they are. @Lee, could you take this patch series into your tree? I addressed all Mark remarks. Changes in v11: - removed "depends on HAS_DMA" from drivers/spi/Kconfig because the driver has no dma support - changed "selects MFD_AT91_USART" to "depends on MFD_AT91_USART" in drivers/spi/Kconfig - changed comment style in spi-at91-usart.c Changes in v10: -fixed kbuild test robot warning Changes in v9: - minor changes - rebased on top of broonie/for-4.19 Changes in v8: - fixed passing an empty mfd cell if "atmel,usart-mode" value is invalid Changes in v7: - synced up SPDIX license with module license - numbering of usart modes starts from 0 insteand of 1 Changes in v6: - removed unused compatible strings from serial and spi drivers Changes in v5: - fixed usage of stdout-path property with atmel_serial driver Changes in v4: - modified the spi driver to use cs gpio support form spi subsystem - fixed dma transfers for serial driver - squashed binding for spi and serial and moved them to mfd/atmel-usart.txt Changes in v3: - fixed spi slaves probing Changes in v2: - added at91-usart mfd driver - modified spi-at91-usart driver to work as mfd driver child - modified atmel_serial driver to work as mfd driver child Changes in v1: - added spi-at91-usart driver Radu Pirea (6): MAINTAINERS: add at91 usart mfd driver dt-bindings: add binding for atmel-usart in SPI mode mfd: at91-usart: added mfd driver for usart MAINTAINERS: add at91 usart spi driver spi: at91-usart: add driver for at91-usart as spi tty/serial: atmel: change the driver to work under at91-usart mfd .../bindings/{serial => mfd}/atmel-usart.txt | 25 +- MAINTAINERS | 16 + drivers/mfd/Kconfig | 9 + drivers/mfd/Makefile | 1 + drivers/mfd/at91-usart.c | 71 +++ drivers/spi/Kconfig | 8 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 432 ++ drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 42 +- include/dt-bindings/mfd/at91-usart.h | 17 + 11 files changed, 606 insertions(+), 17 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) create mode 100644 drivers/mfd/at91-usart.c create mode 100644 drivers/spi/spi-at91-usart.c create mode 100644 include/dt-bindings/mfd/at91-usart.h -- 2.18.0
[PATCH v11 6/6] 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 --- drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 42 --- 2 files changed, 28 insertions(+), 15 deletions(-) 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", @@ -,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; +
[PATCH v11 2/6] dt-bindings: add binding for atmel-usart in SPI mode
This patch moves the bindings for serial from serial/atmel-usart.txt to mfd/atmel-usart.txt and adds bindings for USART in SPI mode. Signed-off-by: Radu Pirea Reviewed-by: Rob Herring Acked-for-MFD-by: Lee Jones Acked-by: Nicolas Ferre --- .../bindings/{serial => mfd}/atmel-usart.txt | 25 +-- include/dt-bindings/mfd/at91-usart.h | 17 + 2 files changed, 40 insertions(+), 2 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) create mode 100644 include/dt-bindings/mfd/at91-usart.h diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/mfd/atmel-usart.txt similarity index 76% rename from Documentation/devicetree/bindings/serial/atmel-usart.txt rename to Documentation/devicetree/bindings/mfd/atmel-usart.txt index 7c0d6b2f53e4..0348fef0f497 100644 --- a/Documentation/devicetree/bindings/serial/atmel-usart.txt +++ b/Documentation/devicetree/bindings/mfd/atmel-usart.txt @@ -1,6 +1,6 @@ * Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART) -Required properties: +Required properties for USART: - compatible: Should be "atmel,-usart" or "atmel,-dbgu" The compatible indicated will be the first SoC to support an additional mode or an USART new feature. @@ -11,7 +11,13 @@ Required properties: Required elements: "usart" - clocks: phandles to input clocks. -Optional properties: +Required properties for USART in SPI mode: +- #size-cells : Must be <0> +- #address-cells : Must be <1> +- cs-gpios: chipselects (internal cs not supported) +- atmel,usart-mode : Must be (found in dt-bindings/mfd/at91-usart.h) + +Optional properties in serial mode: - atmel,use-dma-rx: use of PDC or DMA for receiving data - atmel,use-dma-tx: use of PDC or DMA for transmitting data - {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD line respectively. @@ -62,3 +68,18 @@ Example: dma-names = "tx", "rx"; atmel,fifo-size = <32>; }; + +- SPI mode: + #include + + spi0: spi@f001c000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "atmel,at91rm9200-usart", "atmel,at91sam9260-usart"; + atmel,usart-mode = ; + reg = <0xf001c000 0x100>; + interrupts = <12 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&usart0_clk>; + clock-names = "usart"; + cs-gpios = <&pioB 3 0>; + }; diff --git a/include/dt-bindings/mfd/at91-usart.h b/include/dt-bindings/mfd/at91-usart.h new file mode 100644 index ..2de5bc312e1e --- /dev/null +++ b/include/dt-bindings/mfd/at91-usart.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * This header provides macros for AT91 USART DT bindings. + * + * Copyright (C) 2018 Microchip Technology + * + * Author: Radu Pirea + * + */ + +#ifndef __DT_BINDINGS_AT91_USART_H__ +#define __DT_BINDINGS_AT91_USART_H__ + +#define AT91_USART_MODE_SERIAL 0 +#define AT91_USART_MODE_SPI1 + +#endif /* __DT_BINDINGS_AT91_USART_H__ */ -- 2.18.0
[PATCH 1/3] spi: at91-usart: add power management support
This patch implements power management callback function for USART as SPI driver. Signed-off-by: Radu Pirea --- drivers/spi/spi-at91-usart.c | 61 1 file changed, 61 insertions(+) diff --git a/drivers/spi/spi-at91-usart.c b/drivers/spi/spi-at91-usart.c index a924657642fa..0b07c746453d 100644 --- a/drivers/spi/spi-at91-usart.c +++ b/drivers/spi/spi-at91-usart.c @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -399,6 +400,59 @@ static int at91_usart_spi_probe(struct platform_device *pdev) return ret; } +__maybe_unused static int at91_usart_spi_runtime_suspend(struct device *dev) +{ + struct spi_controller *ctlr = dev_get_drvdata(dev); + struct at91_usart_spi *aus = spi_master_get_devdata(ctlr); + + clk_disable_unprepare(aus->clk); + pinctrl_pm_select_sleep_state(dev); + + return 0; +} + +__maybe_unused static int at91_usart_spi_runtime_resume(struct device *dev) +{ + struct spi_controller *ctrl = dev_get_drvdata(dev); + struct at91_usart_spi *aus = spi_master_get_devdata(ctrl); + + pinctrl_pm_select_default_state(dev); + + return clk_prepare_enable(aus->clk); +} + +__maybe_unused static int at91_usart_spi_suspend(struct device *dev) +{ + struct spi_controller *ctrl = dev_get_drvdata(dev); + int ret; + + ret = spi_controller_suspend(ctrl); + if (ret) + return ret; + + if (!pm_runtime_suspended(dev)) + at91_usart_spi_runtime_suspend(dev); + + return 0; +} + +__maybe_unused static int at91_usart_spi_resume(struct device *dev) +{ + struct spi_controller *ctrl = dev_get_drvdata(dev); + struct at91_usart_spi *aus = spi_master_get_devdata(ctrl); + int ret; + + if (!pm_runtime_suspended(dev)) { + ret = at91_usart_spi_runtime_resume(dev); + if (ret) + return ret; + } + + at91_usart_spi_init(aus); + + return spi_controller_resume(ctrl); +} + static int at91_usart_spi_remove(struct platform_device *pdev) { struct spi_controller *ctlr = platform_get_drvdata(pdev); @@ -409,6 +463,12 @@ static int at91_usart_spi_remove(struct platform_device *pdev) return 0; } +static const struct dev_pm_ops at91_usart_spi_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(at91_usart_spi_suspend, at91_usart_spi_resume) + SET_RUNTIME_PM_OPS(at91_usart_spi_runtime_suspend, + at91_usart_spi_runtime_resume, NULL) +}; + static const struct of_device_id at91_usart_spi_dt_ids[] = { { .compatible = "microchip,at91sam9g45-usart-spi"}, { /* sentinel */} @@ -419,6 +479,7 @@ MODULE_DEVICE_TABLE(of, at91_usart_spi_dt_ids); static struct platform_driver at91_usart_spi_driver = { .driver = { .name = "at91_usart_spi", + .pm = &at91_usart_spi_pm_ops, }, .probe = at91_usart_spi_probe, .remove = at91_usart_spi_remove, -- 2.19.1
[PATCH 0/3] Add PM and DMA support for AT91 USART as SPI
Hi, This patch series improves the SPI driver for AT91 USART IP and adds support for DMA transfers, updates the bindings of driver and PM callback functions. I decided to use DMA only for transfers long than 16 bytes. DMA setup introduces a little overhead and is better to use PIO for short transfers. Radu Pirea (3): spi: at91-usart: add power management support dt-bindings: mfd: atmel-usart: add DMA bindings for SPI mode spi: at91-usart: add DMA support .../devicetree/bindings/mfd/atmel-usart.txt | 15 +- drivers/spi/spi-at91-usart.c | 284 +- 2 files changed, 292 insertions(+), 7 deletions(-) -- 2.19.1
[PATCH 3/3] spi: at91-usart: add DMA support
This patch adds support for DMA. Transfers are done with dma only if they are longer than 16 bytes in order to achieve a better performance. DMA setup introduces a little overhead and for transfers shorter than 16 bytes there is no performance improvement. Signed-off-by: Radu Pirea --- drivers/spi/spi-at91-usart.c | 223 ++- 1 file changed, 221 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-at91-usart.c b/drivers/spi/spi-at91-usart.c index 0b07c746453d..4d908afeaec9 100644 --- a/drivers/spi/spi-at91-usart.c +++ b/drivers/spi/spi-at91-usart.c @@ -8,9 +8,12 @@ #include #include +#include +#include #include #include #include +#include #include #include #include @@ -58,6 +61,8 @@ #define US_INIT \ (US_MR_SPI_MASTER | US_MR_CHRL | US_MR_CLKO | US_MR_WRDBT) +#define US_DMA_MIN_BYTES 16 +#define US_DMA_TIMEOUT (msecs_to_jiffies(1000)) /* Register access macros */ #define at91_usart_spi_readl(port, reg) \ @@ -71,14 +76,19 @@ writeb_relaxed((value), (port)->regs + US_##reg) struct at91_usart_spi { + struct platform_device *mpdev; struct spi_transfer *current_transfer; void __iomem*regs; struct device *dev; struct clk *clk; + struct completion xfer_completion; + /*used in interrupt to protect data reading*/ spinlock_t lock; + phys_addr_t phybase; + int irq; unsigned intcurrent_tx_remaining_bytes; unsigned intcurrent_rx_remaining_bytes; @@ -87,8 +97,184 @@ struct at91_usart_spi { u32 status; boolxfer_failed; + booluse_dma; }; +static void dma_callback(void *data) +{ + struct spi_controller *ctlr = data; + struct at91_usart_spi *aus = spi_master_get_devdata(ctlr); + + at91_usart_spi_writel(aus, IER, US_IR_RXRDY); + aus->current_rx_remaining_bytes = 0; + complete(&aus->xfer_completion); +} + +static bool at91_usart_spi_can_dma(struct spi_controller *ctrl, + struct spi_device *spi, + struct spi_transfer *xfer) +{ + struct at91_usart_spi *aus = spi_master_get_devdata(ctrl); + + return aus->use_dma && xfer->len >= US_DMA_MIN_BYTES; +} + +static int at91_usart_spi_configure_dma(struct spi_controller *ctlr, + struct at91_usart_spi *aus) +{ + struct dma_slave_config slave_config; + struct device *dev = &aus->mpdev->dev; + phys_addr_t phybase = aus->phybase; + dma_cap_mask_t mask; + int err = 0; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + ctlr->dma_tx = dma_request_slave_channel_reason(dev, "tx"); + if (IS_ERR_OR_NULL(ctlr->dma_tx)) { + if (IS_ERR(ctlr->dma_tx)) { + err = PTR_ERR(ctlr->dma_tx); + goto at91_usart_spi_error_clear; + } + + dev_dbg(dev, + "DMA TX channel not available, SPI unable to use DMA\n"); + err = -EBUSY; + goto at91_usart_spi_error_clear; + } + + ctlr->dma_rx = dma_request_slave_channel_reason(dev, "rx"); + if (IS_ERR_OR_NULL(ctlr->dma_rx)) { + if (IS_ERR(ctlr->dma_rx)) { + err = PTR_ERR(ctlr->dma_rx); + goto at91_usart_spi_error; + } + + dev_dbg(dev, + "DMA RX channel not available, SPI unable to use DMA\n"); + err = -EBUSY; + goto at91_usart_spi_error; + } + + slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + slave_config.dst_addr = (dma_addr_t)phybase + US_THR; + slave_config.src_addr = (dma_addr_t)phybase + US_RHR; + slave_config.src_maxburst = 1; + slave_config.dst_maxburst = 1; + slave_config.device_fc = false; + + slave_config.direction = DMA_DEV_TO_MEM; + if (dmaengine_slave_config(ctlr->dma_rx, &slave_config)) { + dev_err(&ctlr->dev, + "failed to configure rx dma channel\n"); + err = -EINVAL; + goto at91_usart_spi_error; + } + + slave_config.direction = DMA_MEM_TO_DEV; + if (dmaengine_slave_config(ctlr->dma_tx, &slave_config)) { + dev_err(&ctlr->dev, + "failed to configure tx dma channel\n"); + err = -EINVAL; + goto at91_usart_spi_error; + } + + aus->use_d
[PATCH 2/3] dt-bindings: mfd: atmel-usart: add DMA bindings for SPI mode
The bindings for DMA are now common for both drivers of the USART IP. The node given as an example for USART in SPI mode has been updated in order to include DMA bindings. Signed-off-by: Radu Pirea --- .../devicetree/bindings/mfd/atmel-usart.txt | 15 ++- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/atmel-usart.txt b/Documentation/devicetree/bindings/mfd/atmel-usart.txt index 7f0cd72f47d2..8ad008175343 100644 --- a/Documentation/devicetree/bindings/mfd/atmel-usart.txt +++ b/Documentation/devicetree/bindings/mfd/atmel-usart.txt @@ -17,17 +17,19 @@ Required properties for USART in SPI mode: - cs-gpios: chipselects (internal cs not supported) - atmel,usart-mode : Must be (found in dt-bindings/mfd/at91-usart.h) +Optional properties in serial and SPI mode: +- dma bindings for dma transfer: + - dmas: DMA specifier, consisting of a phandle to DMA controller node, + memory peripheral interface and USART DMA channel ID, FIFO configuration. + Refer to dma.txt and atmel-dma.txt for details. + - dma-names: "rx" for RX channel, "tx" for TX channel. + Optional properties in serial mode: - atmel,use-dma-rx: use of PDC or DMA for receiving data - atmel,use-dma-tx: use of PDC or DMA for transmitting data - {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD line respectively. It will use specified PIO instead of the peripheral function pin for the USART feature. If unsure, don't specify this property. -- add dma bindings for dma transfer: - - dmas: DMA specifier, consisting of a phandle to DMA controller node, - memory peripheral interface and USART DMA channel ID, FIFO configuration. - Refer to dma.txt and atmel-dma.txt for details. - - dma-names: "rx" for RX channel, "tx" for TX channel. - atmel,fifo-size: maximum number of data the RX and TX FIFOs can store for FIFO capable USARTs. - rs485-rts-delay, rs485-rx-during-tx, linux,rs485-enabled-at-boot-time: see rs485.txt @@ -81,5 +83,8 @@ Example: interrupts = <12 IRQ_TYPE_LEVEL_HIGH 5>; clocks = <&usart0_clk>; clock-names = "usart"; + dmas = <&dma0 2 AT91_DMA_CFG_PER_ID(3)>, + <&dma0 2 (AT91_DMA_CFG_PER_ID(4) | AT91_DMA_CFG_FIFOCFG_ASAP)>; + dma-names = "tx", "rx"; cs-gpios = <&pioB 3 0>; }; -- 2.19.1
[PATCH v10 0/6] Driver for at91 usart in spi mode
Hello, This is the second version of driver. I added a mfd driver which by default probes atmel_serial driver and if in dt is specified to probe the spi driver, then the spi-at91-usart driver will be probed. The compatible for atmel_serial is now the compatible for at91-usart mfd driver and compatilbe for atmel_serial driver was changed in order to keep the bindings for serial as they are. Changes in v10: -fixed kbuild test robot warning Changes in v9: - minor changes - rebased on top of broonie/for-4.19 Changes in v8: - fixed passing an empty mfd cell if "atmel,usart-mode" value is invalid Changes in v7: - synced up SPDIX license with module license - numbering of usart modes starts from 0 insteand of 1 Changes in v6: - removed unused compatible strings from serial and spi drivers Changes in v5: - fixed usage of stdout-path property with atmel_serial driver Changes in v4: - modified the spi driver to use cs gpio support form spi subsystem - fixed dma transfers for serial driver - squashed binding for spi and serial and moved them to mfd/atmel-usart.txt Changes in v3: - fixed spi slaves probing Changes in v2: - added at91-usart mfd driver - modified spi-at91-usart driver to work as mfd driver child - modified atmel_serial driver to work as mfd driver child Changes in v1: - added spi-at91-usart driver Radu Pirea (6): MAINTAINERS: add at91 usart mfd driver dt-bindings: add binding for atmel-usart in SPI mode mfd: at91-usart: added mfd driver for usart MAINTAINERS: add at91 usart spi driver spi: at91-usart: add driver for at91-usart as spi tty/serial: atmel: change the driver to work under at91-usart mfd .../bindings/{serial => mfd}/atmel-usart.txt | 25 +- MAINTAINERS | 16 + drivers/mfd/Kconfig | 9 + drivers/mfd/Makefile | 1 + drivers/mfd/at91-usart.c | 71 +++ drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 432 ++ drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 42 +- include/dt-bindings/mfd/at91-usart.h | 17 + 11 files changed, 607 insertions(+), 17 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) create mode 100644 drivers/mfd/at91-usart.c create mode 100644 drivers/spi/spi-at91-usart.c create mode 100644 include/dt-bindings/mfd/at91-usart.h -- 2.18.0
[PATCH v10 1/6] MAINTAINERS: add at91 usart mfd driver
Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea --- MAINTAINERS | 9 + 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 9d5eeff51b5f..7ac6e6af5292 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9321,6 +9321,7 @@ M:Richard Genoud S: Maintained F: drivers/tty/serial/atmel_serial.c F: drivers/tty/serial/atmel_serial.h +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt MICROCHIP / ATMEL DMA DRIVER M: Ludovic Desroches @@ -9353,6 +9354,14 @@ S: Supported F: drivers/mtd/nand/raw/atmel/* F: Documentation/devicetree/bindings/mtd/atmel-nand.txt +MICROCHIP AT91 USART MFD DRIVER +M: Radu Pirea +L: linux-kernel@vger.kernel.org +S: Supported +F: drivers/mfd/at91-usart.c +F: include/dt-bindings/mfd/at91-usart.h +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.18.0
[PATCH v10 2/6] dt-bindings: add binding for atmel-usart in SPI mode
This patch moves the bindings for serial from serial/atmel-usart.txt to mfd/atmel-usart.txt and adds bindings for USART in SPI mode. Signed-off-by: Radu Pirea Reviewed-by: Rob Herring --- .../bindings/{serial => mfd}/atmel-usart.txt | 25 +-- include/dt-bindings/mfd/at91-usart.h | 17 + 2 files changed, 40 insertions(+), 2 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) create mode 100644 include/dt-bindings/mfd/at91-usart.h diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/mfd/atmel-usart.txt similarity index 76% rename from Documentation/devicetree/bindings/serial/atmel-usart.txt rename to Documentation/devicetree/bindings/mfd/atmel-usart.txt index 7c0d6b2f53e4..0348fef0f497 100644 --- a/Documentation/devicetree/bindings/serial/atmel-usart.txt +++ b/Documentation/devicetree/bindings/mfd/atmel-usart.txt @@ -1,6 +1,6 @@ * Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART) -Required properties: +Required properties for USART: - compatible: Should be "atmel,-usart" or "atmel,-dbgu" The compatible indicated will be the first SoC to support an additional mode or an USART new feature. @@ -11,7 +11,13 @@ Required properties: Required elements: "usart" - clocks: phandles to input clocks. -Optional properties: +Required properties for USART in SPI mode: +- #size-cells : Must be <0> +- #address-cells : Must be <1> +- cs-gpios: chipselects (internal cs not supported) +- atmel,usart-mode : Must be (found in dt-bindings/mfd/at91-usart.h) + +Optional properties in serial mode: - atmel,use-dma-rx: use of PDC or DMA for receiving data - atmel,use-dma-tx: use of PDC or DMA for transmitting data - {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD line respectively. @@ -62,3 +68,18 @@ Example: dma-names = "tx", "rx"; atmel,fifo-size = <32>; }; + +- SPI mode: + #include + + spi0: spi@f001c000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "atmel,at91rm9200-usart", "atmel,at91sam9260-usart"; + atmel,usart-mode = ; + reg = <0xf001c000 0x100>; + interrupts = <12 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&usart0_clk>; + clock-names = "usart"; + cs-gpios = <&pioB 3 0>; + }; diff --git a/include/dt-bindings/mfd/at91-usart.h b/include/dt-bindings/mfd/at91-usart.h new file mode 100644 index ..2de5bc312e1e --- /dev/null +++ b/include/dt-bindings/mfd/at91-usart.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * This header provides macros for AT91 USART DT bindings. + * + * Copyright (C) 2018 Microchip Technology + * + * Author: Radu Pirea + * + */ + +#ifndef __DT_BINDINGS_AT91_USART_H__ +#define __DT_BINDINGS_AT91_USART_H__ + +#define AT91_USART_MODE_SERIAL 0 +#define AT91_USART_MODE_SPI1 + +#endif /* __DT_BINDINGS_AT91_USART_H__ */ -- 2.18.0
[PATCH v10 5/6] 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 --- drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 432 +++ 3 files changed, 442 insertions(+) create mode 100644 drivers/spi/spi-at91-usart.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index ad5d68e1dab7..02bb35057ccd 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -83,6 +83,15 @@ 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 HAS_DMA + depends on (ARCH_AT91 || COMPILE_TEST) + select 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 cb1f4378b87c..901ff606e6e5 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 ..5c6dd0d2c6a7 --- /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_BRGR0x20 +#define US_VERSION 0xFC + +#define US_CR_RSTRXBIT(2) +#define US_CR_RSTTXBIT(3) +#define US_CR_RXEN BIT(4) +#define US_CR_RXDISBIT(5) +#define US_CR_TXEN BIT(6) +#define US_CR_TXDISBIT(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_WRDBTBIT(20) +#define US_MR_LOOP BIT(15) + +#define US_IR_RXRDYBIT(0) +#define US_IR_TXRDYBIT(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 intcurrent_tx_remaining_bytes; + unsigned intcurrent_rx_remaining_bytes; + + u32 spi_clk; + u32 status; + + boolxfer_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_
[PATCH v10 6/6] 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 Acked-by: Richard Genoud Reviewed-by: Andy Shevchenko --- drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 42 --- 2 files changed, 28 insertions(+), 15 deletions(-) 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", @@ -,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
[PATCH v10 4/6] MAINTAINERS: add at91 usart spi driver
Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea --- MAINTAINERS | 7 +++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 7ac6e6af5292..f849cc4acbf6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9362,6 +9362,13 @@ F: drivers/mfd/at91-usart.c F: include/dt-bindings/mfd/at91-usart.h F: Documentation/devicetree/bindings/mfd/atmel-usart.txt +MICROCHIP AT91 USART SPI DRIVER +M: Radu Pirea +L: linux-...@vger.kernel.org +S: Supported +F: drivers/spi/spi-at91-usart.c +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.18.0
[PATCH v10 3/6] mfd: at91-usart: added 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 Acked-by: Rob Herring Reviewed-by: Andy Shevchenko Acked-for-MFD-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 diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b860eb5aa194..a886672b960d 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 e9fd20dba18d..c7e66928abb9 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -184,6 +184,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 ..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"); -- 2.18.0
Re: [PATCH v3 5/6] spi: at91-usart: add driver for at91-usart as spi
On 05/17/2018 07:54 AM, Mark Brown wrote: On Tue, May 15, 2018 at 12:22:24PM +0300, Radu Pirea wrote: On Mon, 2018-05-14 at 20:38 +0300, Andy Shevchenko wrote: So, what is not going as expected in "SPI core takes care of CSs" case? Did you use oscilloscope for that? Yes, I used and CSs was not asserted. Anyway, I will will try again. If the core chip select handling is not working properly for some reason then the core chip select handling should be fixed rather than just open coding in your driver - probably it's also broken for other users. Hi Mark, I found the fix for cs-gpios. If I change spi_add_device function like this(see below) everything is ok. int spi_add_device(struct spi_device *spi) ... if (ctlr->cs_gpios){ spi->cs_gpio = ctlr->cs_gpios[spi->chip_select]; if(gpio_is_valid(spi->cs_gpio)) gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); } ... return status; } In the subsystem gpio direction of pins is never set and gpio_set_value() don't set the direction. In my opinion gpio_direction_output() set direction should be called in spi_add_device. What do you think? Is ok?
Re: [PATCH v3 6/6] tty/serial: atmel: changed the driver to work under at91-usart mfd
On 05/15/2018 04:14 PM, Richard Genoud wrote: On 15/05/2018 14:47, Radu Pirea wrote: On Mon, 2018-05-14 at 12:57 +0200, Richard Genoud wrote: After your patch, the DMA is not selected anymore: atmel_usart_serial atmel_usart_serial.0.auto: TX channel not available, switch to pio instead of: atmel_usart f200.serial: using dma1chan2 for tx DMA transfers Fixed. And the kernel doesn't log anymore on the serial console, despite the loglevel=8 (after reverting this series, the kernel logs reappears on the serial console) Which serial are you using as console? f200.serial (sam9g35-cm) ( stdout-path = "serial0:115200n8"; in the DTS ) With this series applied, all the kernel log goes on the screen. Without, it goes on the serial debug. I tested again with archlinux arm and poky-linux4sam release as distros and kernel log goes on the serial debug. Can you give me more details like cmdline? (tests done on sam9g35) I will consider the rest of suggestions. regards, Richard
Re: [PATCH v3 6/6] tty/serial: atmel: changed the driver to work under at91-usart mfd
On 05/25/2018 04:35 PM, Richard Genoud wrote: On 25/05/2018 14:17, Radu Pirea wrote: On 05/15/2018 04:14 PM, Richard Genoud wrote: On 15/05/2018 14:47, Radu Pirea wrote: On Mon, 2018-05-14 at 12:57 +0200, Richard Genoud wrote: After your patch, the DMA is not selected anymore: atmel_usart_serial atmel_usart_serial.0.auto: TX channel not available, switch to pio instead of: atmel_usart f200.serial: using dma1chan2 for tx DMA transfers Fixed. And the kernel doesn't log anymore on the serial console, despite the loglevel=8 (after reverting this series, the kernel logs reappears on the serial console) Which serial are you using as console? f200.serial (sam9g35-cm) ( stdout-path = "serial0:115200n8"; in the DTS ) With this series applied, all the kernel log goes on the screen. Without, it goes on the serial debug. I tested again with archlinux arm and poky-linux4sam release as distros and kernel log goes on the serial debug. Can you give me more details like cmdline? I used kernel 4.17-rc6 at91_dt_defconfig at91sam9g35ek.dtb Kernel command line: root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs I reproduced your issue. If in cmdline console is not set like this "console=ttyS0,115200", the console goes to the lcd. ( the one from the DTS ) Detailed instructions: git checkout v4.17-rc6 ARCH=arm CROSS_COMPILE=path_to_my_Xchain/arm-linux- LOADADDR=0x20008000 make -j 12 at91_dt_defconfig ARCH=arm CROSS_COMPILE=path_to_my_Xchain/arm-linux- LOADADDR=0x20008000 make -j 12 uImage at91sam9g35ek.dtb cp arch/arm/boot/uImage arch/arm/boot/dts/at91sam9g35ek.dtb /tftpboot/ From uboot: tftpboot 0x20007FC0 uImage tftpboot 0x2640 at91sam9g35ek.dtb bootm 0x20007FC0 - 0x2640 [ I see the logs on the serial debug ] git am \[PATCH\ v3\ [1-6]* ARCH=arm CROSS_COMPILE=path_to_my_Xchain/arm-linux- LOADADDR=0x20008000 make -j 12 uImage at91sam9g35ek.dtb cp arch/arm/boot/uImage arch/arm/boot/dts/at91sam9g35ek.dtb /tftpboot/ From uboot: tftpboot 0x20007FC0 uImage tftpboot 0x2640 at91sam9g35ek.dtb bootm 0x20007FC0 - 0x2640 [ I don't see the logs on the serial debug anymore ] (tests done on sam9g35) I will consider the rest of suggestions. regards, Richard
[PATCH v4 1/6] MAINTAINERS: add at91 usart mfd driver
Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea --- MAINTAINERS | 9 + 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 8e2a2fddbd19..12203d07c6af 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9160,6 +9160,7 @@ M:Richard Genoud S: Maintained F: drivers/tty/serial/atmel_serial.c F: drivers/tty/serial/atmel_serial.h +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt MICROCHIP / ATMEL DMA DRIVER M: Ludovic Desroches @@ -9192,6 +9193,14 @@ S: Supported F: drivers/mtd/nand/raw/atmel/* F: Documentation/devicetree/bindings/mtd/atmel-nand.txt +MICROCHIP AT91 USART MFD DRIVER +M: Radu Pirea +L: linux-kernel@vger.kernel.org +S: Supported +F: drivers/mfd/at91-usart.c +F: include/dt-bindings/mfd/at91-usart.h +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.17.0
[PATCH v4 0/6] Driver for at91 usart in spi mode
Hello, This is the second version of driver. I added a mfd driver which by default probes atmel_serial driver and if in dt is specified to probe the spi driver, then the spi-at91-usart driver will be probed. The compatible for atmel_serial is now the compatible for at91-usart mfd driver and compatilbe for atmel_serial driver was changed in order to keep the bindings for serial as they are. Changes in v1: - added spi-at91-usart driver Changes in v2: - added at91-usart mfd driver - modified spi-at91-usart driver to work as mfd driver child - modified atmel_serial driver to work as mfd driver child Changes in v3: - fixed spi slaves probing Changes in v4: - modified the spi driver to use cs gpio support form spi subsystem - fixed dma transfers for serial driver - squashed binding for spi and serial and moved them to mfd/atmel-usart.txt Radu Pirea (6): MAINTAINERS: add at91 usart mfd driver dt-bindings: add binding for atmel-usart in SPI mode mfd: at91-usart: added mfd driver for usart MAINTAINERS: add at91 usart spi driver spi: at91-usart: add driver for at91-usart as spi tty/serial: atmel: changed the driver to work under at91-usart mfd .../bindings/{serial => mfd}/atmel-usart.txt | 25 +- MAINTAINERS | 16 + drivers/mfd/Kconfig | 10 + drivers/mfd/Makefile | 1 + drivers/mfd/at91-usart.c | 75 +++ drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 431 ++ drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 40 +- include/dt-bindings/mfd/at91-usart.h | 17 + 11 files changed, 606 insertions(+), 20 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) create mode 100644 drivers/mfd/at91-usart.c create mode 100644 drivers/spi/spi-at91-usart.c create mode 100644 include/dt-bindings/mfd/at91-usart.h -- 2.17.0
[PATCH v4 3/6] mfd: at91-usart: added 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 --- drivers/mfd/Kconfig | 10 drivers/mfd/Makefile | 1 + drivers/mfd/at91-usart.c | 75 include/dt-bindings/mfd/at91-usart.h | 17 +++ 4 files changed, 103 insertions(+) create mode 100644 drivers/mfd/at91-usart.c create mode 100644 include/dt-bindings/mfd/at91-usart.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b860eb5aa194..de99b79061b7 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -99,6 +99,16 @@ 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 + depends on OF + 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 d9d2cf0d32ef..db1332aa96db 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -185,6 +185,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 ..0535a256a3c0 --- /dev/null +++ b/drivers/mfd/at91-usart.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Driver for AT91 USART + * + * Copyright (C) 2018 Microchip Technology + * + * Author: Radu Pirea + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#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 device_node *np = pdev->dev.of_node; + struct mfd_cell cell; + u32 opmode; + int err; + + err = of_property_read_u32(np, "atmel,usart-mode", &opmode); + + switch (opmode) { + case AT91_USART_MODE_SPI: + cell = at91_usart_spi_subdev; + break; + case AT91_USART_MODE_SERIAL: + default: + cell = at91_usart_serial_subdev; + } + + return 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_flexcom_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"); diff --git a/include/dt-bindings/mfd/at91-usart.h b/include/dt-bindings/mfd/at91-usart.h new file mode 100644 index ..ac811628a42d --- /dev/null +++ b/include/dt-bindings/mfd/at91-usart.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * This header provides macros for AT91 USART DT bindings. + * + * Copyright (C) 2018 Microchip Technology + * + * Author: Radu Pirea + * + */ + +#ifndef __DT_BINDINGS_AT91_USART_H__ +#define __DT_BINDINGS_AT91_USART_H__ + +#define AT91_USART_MODE_SERIAL 1 +#define AT91_USART_MODE_SPI2 + +#endif /* __DT_BINDINGS_AT91_USART_H__ */ -- 2.17.0
[PATCH v4 2/6] dt-bindings: add binding for atmel-usart in SPI mode
This patch moves the bindings for serial from serial/atmel-usart.txt to mfd/atmel-usart.txt and adds bindings for USART in SPI mode. Signed-off-by: Radu Pirea --- .../bindings/{serial => mfd}/atmel-usart.txt | 25 +-- 1 file changed, 23 insertions(+), 2 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/mfd/atmel-usart.txt similarity index 76% rename from Documentation/devicetree/bindings/serial/atmel-usart.txt rename to Documentation/devicetree/bindings/mfd/atmel-usart.txt index 7c0d6b2f53e4..3b9e18642c3b 100644 --- a/Documentation/devicetree/bindings/serial/atmel-usart.txt +++ b/Documentation/devicetree/bindings/mfd/atmel-usart.txt @@ -1,6 +1,6 @@ * Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART) -Required properties: +Required properties for USART: - compatible: Should be "atmel,-usart" or "atmel,-dbgu" The compatible indicated will be the first SoC to support an additional mode or an USART new feature. @@ -11,7 +11,13 @@ Required properties: Required elements: "usart" - clocks: phandles to input clocks. -Optional properties: +Required properties for USART in SPI mode: +- #size-cells : Must be <0> +- #address-cells : Must be <1> +- cs-gpios: chipselects (internal cs not supported) +- atmel,usart-mode : Must be (found in dt-bindings/mfd/at91-usart.h) + +Optional properties in serial mode: - atmel,use-dma-rx: use of PDC or DMA for receiving data - atmel,use-dma-tx: use of PDC or DMA for transmitting data - {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD line respectively. @@ -62,3 +68,18 @@ Example: dma-names = "tx", "rx"; atmel,fifo-size = <32>; }; + +- SPI mode: + #include + + spi0: spi@f001c000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "atmel,at91rm9200-usart", "atmel,at91sam9260-usart"; + atmel,usart-mode = ; + reg = <0xf001c000 0x100>; + interrupts = <12 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&usart0_clk>; + clock-names = "usart"; + cs-gpios = <&pioB 3 0>; + }; -- 2.17.0
[PATCH v4 6/6] tty/serial: atmel: changed 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 --- drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 40 +-- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 3682fd3e960c..25e55332f8b1 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -119,6 +119,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 df46a9e88c34..740c7d7f4a0c 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -193,8 +193,8 @@ 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" }, + { .compatible = "atmel,at91sam9260-usart-serial" }, { /* sentinel */ } }; #endif @@ -915,6 +915,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 +923,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 +1094,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 +1106,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", @@ -1631,7 +1633,7 @@ static void atmel_tasklet_tx_func(unsigned long data) static void atmel_init_property(struct atmel_uart_port *atmel_port, struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; + struct device_node *np = pdev->dev.parent->of_node; /* DMA/PDC usage specification */ if (of_property_read_bool(np, "atmel,use-dma-rx")) { @@ -,8 +2224,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 +2240,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 +2343,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_g
[PATCH v4 4/6] MAINTAINERS: add at91 usart spi driver
Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea --- MAINTAINERS | 7 +++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 12203d07c6af..dae31df711fb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9201,6 +9201,13 @@ F: drivers/mfd/at91-usart.c F: include/dt-bindings/mfd/at91-usart.h F: Documentation/devicetree/bindings/mfd/atmel-usart.txt +MICROCHIP AT91 USART SPI DRIVER +M: Radu Pirea +L: linux-...@vger.kernel.org +S: Supported +F: drivers/spi/spi-at91-usart.c +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.17.0
[PATCH v4 5/6] 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 --- drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 431 +++ 3 files changed, 441 insertions(+) create mode 100644 drivers/spi/spi-at91-usart.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 6fb0347a24f2..1a002a32d7aa 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -77,6 +77,15 @@ 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 HAS_DMA + depends on (ARCH_AT91 || COMPILE_TEST) + select 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 34c5f2832ddf..fb6cb42f4eaa 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -15,6 +15,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 ..3ca0fab6691e --- /dev/null +++ b/drivers/spi/spi-at91-usart.c @@ -0,0 +1,431 @@ +// 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_BRGR0x20 +#define US_VERSION 0xFC + +#define US_CR_RSTRXBIT(2) +#define US_CR_RSTTXBIT(3) +#define US_CR_RXEN BIT(4) +#define US_CR_RXDISBIT(5) +#define US_CR_TXEN BIT(6) +#define US_CR_TXDISBIT(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_WRDBTBIT(20) +#define US_MR_LOOP BIT(15) + +#define US_IR_RXRDYBIT(0) +#define US_IR_TXRDYBIT(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 spi_readl(port, reg) \ + readl_relaxed((port)->regs + US_##reg) +#define spi_writel(port, reg, value) \ + writel_relaxed((value), (port)->regs + US_##reg) + +#define spi_readb(port, reg) \ + readb_relaxed((port)->regs + US_##reg) +#define 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 intcurrent_tx_remaining_bytes; + unsigned intcurrent_rx_remaining_bytes; + int done_status; + + u32 spi_clk; + u32 status; + + boolxfer_failed; +}; + +static inline u32 at91_usart_spi_tx_ready(struct at91_usart_spi *aus) +{ + return aus->status & US_IR_TXRDY; +} + +st
[PATCH v3 6/6] tty/serial: atmel: changed 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 --- drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 29 +++-- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 3682fd3e960c..25e55332f8b1 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -119,6 +119,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 df46a9e88c34..6b4494352853 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -193,8 +193,8 @@ 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" }, + { .compatible = "atmel,at91sam9260-usart-serial" }, { /* sentinel */ } }; #endif @@ -1631,7 +1631,7 @@ static void atmel_tasklet_tx_func(unsigned long data) static void atmel_init_property(struct atmel_uart_port *atmel_port, struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; + struct device_node *np = pdev->dev.parent->of_node; /* DMA/PDC usage specification */ if (of_property_read_bool(np, "atmel,use-dma-rx")) { @@ -2223,7 +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; + int size = to_platform_device(pdev->dev.parent)->resource[0].end - + to_platform_device(pdev->dev.parent)->resource[0].start + 1; release_mem_region(port->mapbase, size); @@ -2239,7 +2240,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; + int size = to_platform_device(pdev->dev.parent)->resource[0].end - + to_platform_device(pdev->dev.parent)->resource[0].start + 1; if (!request_mem_region(port->mapbase, size, "atmel_serial")) return -EBUSY; @@ -2345,23 +2347,23 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port, atmel_init_property(atmel_port, pdev); atmel_set_ops(port); - uart_get_rs485_mode(&pdev->dev, &port->rs485); + uart_get_rs485_mode(pdev->dev.parent, &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 = to_platform_device(pdev->dev.parent)->resource[0].start; + port->irq = to_platform_device(pdev->dev.parent)->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(pdev->dev.parent, "usart"); if (IS_ERR(atmel_port->clk)) { ret = PTR_ERR(atmel_port->clk); atmel_port->clk = NULL; @@ -2656,7 +2658,7 @@ static void atmel_serial_probe_fifos(struct atmel_uart_port *atmel_port, atmel_port->rts_low = 0; atmel_port->rts_high = 0; - if (of_property_read_u32(pdev->dev.of_node, + if (of_property_read_u32(pdev->dev.parent->of_node, "atmel,fifo-size", &atmel_port->fifo_size)) return; @@ -2694,11 +2696,10 @@ static void atmel_serial_probe_fifos(struct atmel_uart_p
[PATCH v3 5/6] 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 --- drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 544 +++ 3 files changed, 554 insertions(+) create mode 100644 drivers/spi/spi-at91-usart.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 6fb0347a24f2..c675e6b8dd5a 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -77,6 +77,15 @@ 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 as SPI" + depends on HAS_DMA + depends on (ARCH_AT91 || COMPILE_TEST) +select 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 34c5f2832ddf..fb6cb42f4eaa 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -15,6 +15,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 ..79a59759d2ee --- /dev/null +++ b/drivers/spi/spi-at91-usart.c @@ -0,0 +1,544 @@ +// 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 +#include +#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_BRGR0x20 +#define US_VERSION 0xFC + +#define US_CR_RSTRXBIT(2) +#define US_CR_RSTTXBIT(3) +#define US_CR_RXEN BIT(4) +#define US_CR_RXDISBIT(5) +#define US_CR_TXEN BIT(6) +#define US_CR_TXDISBIT(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_WRDBTBIT(20) +#define US_MR_LOOP BIT(15) + +#define US_IR_RXRDYBIT(0) +#define US_IR_TXRDYBIT(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_DUMMY_TX0xFF + +/* Register access macros */ +#define spi_readl(port, reg) \ + readl_relaxed((port)->regs + US_##reg) +#define spi_writel(port, reg, value) \ + writel_relaxed((value), (port)->regs + US_##reg) + +#define spi_readb(port, reg) \ + readb_relaxed((port)->regs + US_##reg) +#define 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 intcurrent_tx_remaining_bytes; + unsigned intcurrent_rx_remaining_bytes; + int done_status; + + u32 spi_clk; + u32 status; + + boolxfer_failed; + boolkeep_cs; + boolcs_active; +}; + +struct at91_usart_spi_device { + struct gpio_desc*npcs_pin; + u32 mr; +}; + +static inline u32 at91_usart_spi_tx_ready(struct at91_usart_spi *aus) +{ + return aus->status & US_IR_TXRDY; +} + +static inline u32 at91_usart_
[PATCH v3 3/6] MAINTAINERS: add at91 usart spi driver
Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea --- MAINTAINERS | 7 +++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index ca06c6f58299..9243b9007966 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9199,6 +9199,13 @@ S: Supported F: drivers/mfd/at91-usart.c F: include/dt-bindings/mfd/at91-usart.h +MICROCHIP AT91 USART SPI DRIVER +M: Radu Pirea +L: linux-...@vger.kernel.org +S: Supported +F: drivers/spi/spi-at91-usart.c +F: Documentation/devicetree/bindings/spi/microchip,at91-usart-spi.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.17.0
[PATCH v8 1/6] MAINTAINERS: add at91 usart mfd driver
Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea --- MAINTAINERS | 9 + 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 8e2a2fddbd19..12203d07c6af 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9160,6 +9160,7 @@ M:Richard Genoud S: Maintained F: drivers/tty/serial/atmel_serial.c F: drivers/tty/serial/atmel_serial.h +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt MICROCHIP / ATMEL DMA DRIVER M: Ludovic Desroches @@ -9192,6 +9193,14 @@ S: Supported F: drivers/mtd/nand/raw/atmel/* F: Documentation/devicetree/bindings/mtd/atmel-nand.txt +MICROCHIP AT91 USART MFD DRIVER +M: Radu Pirea +L: linux-kernel@vger.kernel.org +S: Supported +F: drivers/mfd/at91-usart.c +F: include/dt-bindings/mfd/at91-usart.h +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.17.1
[PATCH v8 2/6] dt-bindings: add binding for atmel-usart in SPI mode
This patch moves the bindings for serial from serial/atmel-usart.txt to mfd/atmel-usart.txt and adds bindings for USART in SPI mode. Signed-off-by: Radu Pirea Reviewed-by: Rob Herring --- .../bindings/{serial => mfd}/atmel-usart.txt | 25 +-- include/dt-bindings/mfd/at91-usart.h | 17 + 2 files changed, 40 insertions(+), 2 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) create mode 100644 include/dt-bindings/mfd/at91-usart.h diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/mfd/atmel-usart.txt similarity index 76% rename from Documentation/devicetree/bindings/serial/atmel-usart.txt rename to Documentation/devicetree/bindings/mfd/atmel-usart.txt index 7c0d6b2f53e4..3b9e18642c3b 100644 --- a/Documentation/devicetree/bindings/serial/atmel-usart.txt +++ b/Documentation/devicetree/bindings/mfd/atmel-usart.txt @@ -1,6 +1,6 @@ * Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART) -Required properties: +Required properties for USART: - compatible: Should be "atmel,-usart" or "atmel,-dbgu" The compatible indicated will be the first SoC to support an additional mode or an USART new feature. @@ -11,7 +11,13 @@ Required properties: Required elements: "usart" - clocks: phandles to input clocks. -Optional properties: +Required properties for USART in SPI mode: +- #size-cells : Must be <0> +- #address-cells : Must be <1> +- cs-gpios: chipselects (internal cs not supported) +- atmel,usart-mode : Must be (found in dt-bindings/mfd/at91-usart.h) + +Optional properties in serial mode: - atmel,use-dma-rx: use of PDC or DMA for receiving data - atmel,use-dma-tx: use of PDC or DMA for transmitting data - {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD line respectively. @@ -62,3 +68,18 @@ Example: dma-names = "tx", "rx"; atmel,fifo-size = <32>; }; + +- SPI mode: + #include + + spi0: spi@f001c000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "atmel,at91rm9200-usart", "atmel,at91sam9260-usart"; + atmel,usart-mode = ; + reg = <0xf001c000 0x100>; + interrupts = <12 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&usart0_clk>; + clock-names = "usart"; + cs-gpios = <&pioB 3 0>; + }; diff --git a/include/dt-bindings/mfd/at91-usart.h b/include/dt-bindings/mfd/at91-usart.h new file mode 100644 index ..2de5bc312e1e --- /dev/null +++ b/include/dt-bindings/mfd/at91-usart.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * This header provides macros for AT91 USART DT bindings. + * + * Copyright (C) 2018 Microchip Technology + * + * Author: Radu Pirea + * + */ + +#ifndef __DT_BINDINGS_AT91_USART_H__ +#define __DT_BINDINGS_AT91_USART_H__ + +#define AT91_USART_MODE_SERIAL 0 +#define AT91_USART_MODE_SPI1 + +#endif /* __DT_BINDINGS_AT91_USART_H__ */ -- 2.17.1
[PATCH v8 6/6] 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 Acked-by: Richard Genoud Reviewed-by: Andy Shevchenko --- drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 42 --- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 3682fd3e960c..25e55332f8b1 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -119,6 +119,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 df46a9e88c34..107114d73c5d 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", @@ -,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
[PATCH v8 5/6] 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 --- drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 434 +++ 3 files changed, 444 insertions(+) create mode 100644 drivers/spi/spi-at91-usart.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 6fb0347a24f2..1a002a32d7aa 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -77,6 +77,15 @@ 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 HAS_DMA + depends on (ARCH_AT91 || COMPILE_TEST) + select 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 34c5f2832ddf..fb6cb42f4eaa 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -15,6 +15,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 ..ae889aa6bda3 --- /dev/null +++ b/drivers/spi/spi-at91-usart.c @@ -0,0 +1,434 @@ +// 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_BRGR0x20 +#define US_VERSION 0xFC + +#define US_CR_RSTRXBIT(2) +#define US_CR_RSTTXBIT(3) +#define US_CR_RXEN BIT(4) +#define US_CR_RXDISBIT(5) +#define US_CR_TXEN BIT(6) +#define US_CR_TXDISBIT(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_WRDBTBIT(20) +#define US_MR_LOOP BIT(15) + +#define US_IR_RXRDYBIT(0) +#define US_IR_TXRDYBIT(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 intcurrent_tx_remaining_bytes; + unsigned intcurrent_rx_remaining_bytes; + int done_status; + + u32 spi_clk; + u32 status; + + boolxfer_failed; +}; + +static inline u32 at91_usart_spi_tx_ready(struct at91_usart_spi *aus) +{ + return aus->status &am
[PATCH v8 4/6] MAINTAINERS: add at91 usart spi driver
Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea --- MAINTAINERS | 7 +++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 12203d07c6af..dae31df711fb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9201,6 +9201,13 @@ F: drivers/mfd/at91-usart.c F: include/dt-bindings/mfd/at91-usart.h F: Documentation/devicetree/bindings/mfd/atmel-usart.txt +MICROCHIP AT91 USART SPI DRIVER +M: Radu Pirea +L: linux-...@vger.kernel.org +S: Supported +F: drivers/spi/spi-at91-usart.c +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.17.1
[PATCH v8 3/6] mfd: at91-usart: added 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 Acked-by: Rob Herring Reviewed-by: Andy Shevchenko Acked-for-MFD-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 diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b860eb5aa194..a886672b960d 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 d9d2cf0d32ef..db1332aa96db 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -185,6 +185,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 ..ba5754a1b7af --- /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_flexcom_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"); -- 2.17.1
[PATCH v8 0/6] Driver for at91 usart in spi mode
Hello, This is the second version of driver. I added a mfd driver which by default probes atmel_serial driver and if in dt is specified to probe the spi driver, then the spi-at91-usart driver will be probed. The compatible for atmel_serial is now the compatible for at91-usart mfd driver and compatilbe for atmel_serial driver was changed in order to keep the bindings for serial as they are. Changes in v8: - fixed passing an empty mfd cell if "atmel,usart-mode" value is invalid Changes in v7: - synced up SPDIX license with module license - numbering of usart modes starts from 0 insteand of 1 Changes in v6: - removed unused compatible strings from serial and spi drivers Changes in v5: - fixed usage of stdout-path property with atmel_serial driver Changes in v4: - modified the spi driver to use cs gpio support form spi subsystem - fixed dma transfers for serial driver - squashed binding for spi and serial and moved them to mfd/atmel-usart.txt Changes in v3: - fixed spi slaves probing Changes in v2: - added at91-usart mfd driver - modified spi-at91-usart driver to work as mfd driver child - modified atmel_serial driver to work as mfd driver child Changes in v1: - added spi-at91-usart driver Radu Pirea (6): MAINTAINERS: add at91 usart mfd driver dt-bindings: add binding for atmel-usart in SPI mode mfd: at91-usart: added mfd driver for usart MAINTAINERS: add at91 usart spi driver spi: at91-usart: add driver for at91-usart as spi tty/serial: atmel: change the driver to work under at91-usart mfd .../bindings/{serial => mfd}/atmel-usart.txt | 25 +- MAINTAINERS | 16 + drivers/mfd/Kconfig | 9 + drivers/mfd/Makefile | 1 + drivers/mfd/at91-usart.c | 71 +++ drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 434 ++ drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 42 +- include/dt-bindings/mfd/at91-usart.h | 17 + 11 files changed, 609 insertions(+), 17 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) create mode 100644 drivers/mfd/at91-usart.c create mode 100644 drivers/spi/spi-at91-usart.c create mode 100644 include/dt-bindings/mfd/at91-usart.h -- 2.17.1
[PATCH v7 0/6] Driver for at91 usart in spi mode
Hello, This is the second version of driver. I added a mfd driver which by default probes atmel_serial driver and if in dt is specified to probe the spi driver, then the spi-at91-usart driver will be probed. The compatible for atmel_serial is now the compatible for at91-usart mfd driver and compatilbe for atmel_serial driver was changed in order to keep the bindings for serial as they are. Changes in v7: - synced up SPDIX license with module license - numbering of usart modes starts from 0 insteand of 1 Changes in v6: - removed unused compatible strings from serial and spi drivers Changes in v5: - fixed usage of stdout-path property with atmel_serial driver Changes in v4: - modified the spi driver to use cs gpio support form spi subsystem - fixed dma transfers for serial driver - squashed binding for spi and serial and moved them to mfd/atmel-usart.txt Changes in v3: - fixed spi slaves probing Changes in v2: - added at91-usart mfd driver - modified spi-at91-usart driver to work as mfd driver child - modified atmel_serial driver to work as mfd driver child Changes in v1: - added spi-at91-usart driver Radu Pirea (6): MAINTAINERS: add at91 usart mfd driver dt-bindings: add binding for atmel-usart in SPI mode mfd: at91-usart: added mfd driver for usart MAINTAINERS: add at91 usart spi driver spi: at91-usart: add driver for at91-usart as spi tty/serial: atmel: change the driver to work under at91-usart mfd .../bindings/{serial => mfd}/atmel-usart.txt | 25 +- MAINTAINERS | 16 + drivers/mfd/Kconfig | 9 + drivers/mfd/Makefile | 1 + drivers/mfd/at91-usart.c | 69 +++ drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 434 ++ drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 42 +- include/dt-bindings/mfd/at91-usart.h | 17 + 11 files changed, 607 insertions(+), 17 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) create mode 100644 drivers/mfd/at91-usart.c create mode 100644 drivers/spi/spi-at91-usart.c create mode 100644 include/dt-bindings/mfd/at91-usart.h -- 2.17.1
[PATCH v7 1/6] MAINTAINERS: add at91 usart mfd driver
Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea --- MAINTAINERS | 9 + 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 8e2a2fddbd19..12203d07c6af 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9160,6 +9160,7 @@ M:Richard Genoud S: Maintained F: drivers/tty/serial/atmel_serial.c F: drivers/tty/serial/atmel_serial.h +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt MICROCHIP / ATMEL DMA DRIVER M: Ludovic Desroches @@ -9192,6 +9193,14 @@ S: Supported F: drivers/mtd/nand/raw/atmel/* F: Documentation/devicetree/bindings/mtd/atmel-nand.txt +MICROCHIP AT91 USART MFD DRIVER +M: Radu Pirea +L: linux-kernel@vger.kernel.org +S: Supported +F: drivers/mfd/at91-usart.c +F: include/dt-bindings/mfd/at91-usart.h +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.17.1
[PATCH v7 3/6] mfd: at91-usart: added 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 Acked-by: Rob Herring Reviewed-by: Andy Shevchenko Acked-for-MFD-by: Lee Jones --- drivers/mfd/Kconfig | 9 ++ drivers/mfd/Makefile | 1 + drivers/mfd/at91-usart.c | 69 3 files changed, 79 insertions(+) create mode 100644 drivers/mfd/at91-usart.c diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b860eb5aa194..a886672b960d 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 d9d2cf0d32ef..db1332aa96db 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -185,6 +185,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 ..3014ce532644 --- /dev/null +++ b/drivers/mfd/at91-usart.c @@ -0,0 +1,69 @@ +// 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: + break; + } + + 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_flexcom_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"); -- 2.17.1
[PATCH v7 5/6] 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 --- drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 434 +++ 3 files changed, 444 insertions(+) create mode 100644 drivers/spi/spi-at91-usart.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 6fb0347a24f2..1a002a32d7aa 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -77,6 +77,15 @@ 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 HAS_DMA + depends on (ARCH_AT91 || COMPILE_TEST) + select 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 34c5f2832ddf..fb6cb42f4eaa 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -15,6 +15,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 ..ae889aa6bda3 --- /dev/null +++ b/drivers/spi/spi-at91-usart.c @@ -0,0 +1,434 @@ +// 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_BRGR0x20 +#define US_VERSION 0xFC + +#define US_CR_RSTRXBIT(2) +#define US_CR_RSTTXBIT(3) +#define US_CR_RXEN BIT(4) +#define US_CR_RXDISBIT(5) +#define US_CR_TXEN BIT(6) +#define US_CR_TXDISBIT(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_WRDBTBIT(20) +#define US_MR_LOOP BIT(15) + +#define US_IR_RXRDYBIT(0) +#define US_IR_TXRDYBIT(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 intcurrent_tx_remaining_bytes; + unsigned intcurrent_rx_remaining_bytes; + int done_status; + + u32 spi_clk; + u32 status; + + boolxfer_failed; +}; + +static inline u32 at91_usart_spi_tx_ready(struct at91_usart_spi *aus) +{ + return aus->status &am
[PATCH v7 6/6] 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 Acked-by: Richard Genoud Reviewed-by: Andy Shevchenko --- drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 42 --- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 3682fd3e960c..25e55332f8b1 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -119,6 +119,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 df46a9e88c34..107114d73c5d 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", @@ -,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
[PATCH v7 4/6] MAINTAINERS: add at91 usart spi driver
Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea --- MAINTAINERS | 7 +++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 12203d07c6af..dae31df711fb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9201,6 +9201,13 @@ F: drivers/mfd/at91-usart.c F: include/dt-bindings/mfd/at91-usart.h F: Documentation/devicetree/bindings/mfd/atmel-usart.txt +MICROCHIP AT91 USART SPI DRIVER +M: Radu Pirea +L: linux-...@vger.kernel.org +S: Supported +F: drivers/spi/spi-at91-usart.c +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.17.1
[PATCH v7 2/6] dt-bindings: add binding for atmel-usart in SPI mode
This patch moves the bindings for serial from serial/atmel-usart.txt to mfd/atmel-usart.txt and adds bindings for USART in SPI mode. Signed-off-by: Radu Pirea Reviewed-by: Rob Herring --- .../bindings/{serial => mfd}/atmel-usart.txt | 25 +-- include/dt-bindings/mfd/at91-usart.h | 17 + 2 files changed, 40 insertions(+), 2 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) create mode 100644 include/dt-bindings/mfd/at91-usart.h diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/mfd/atmel-usart.txt similarity index 76% rename from Documentation/devicetree/bindings/serial/atmel-usart.txt rename to Documentation/devicetree/bindings/mfd/atmel-usart.txt index 7c0d6b2f53e4..3b9e18642c3b 100644 --- a/Documentation/devicetree/bindings/serial/atmel-usart.txt +++ b/Documentation/devicetree/bindings/mfd/atmel-usart.txt @@ -1,6 +1,6 @@ * Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART) -Required properties: +Required properties for USART: - compatible: Should be "atmel,-usart" or "atmel,-dbgu" The compatible indicated will be the first SoC to support an additional mode or an USART new feature. @@ -11,7 +11,13 @@ Required properties: Required elements: "usart" - clocks: phandles to input clocks. -Optional properties: +Required properties for USART in SPI mode: +- #size-cells : Must be <0> +- #address-cells : Must be <1> +- cs-gpios: chipselects (internal cs not supported) +- atmel,usart-mode : Must be (found in dt-bindings/mfd/at91-usart.h) + +Optional properties in serial mode: - atmel,use-dma-rx: use of PDC or DMA for receiving data - atmel,use-dma-tx: use of PDC or DMA for transmitting data - {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD line respectively. @@ -62,3 +68,18 @@ Example: dma-names = "tx", "rx"; atmel,fifo-size = <32>; }; + +- SPI mode: + #include + + spi0: spi@f001c000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "atmel,at91rm9200-usart", "atmel,at91sam9260-usart"; + atmel,usart-mode = ; + reg = <0xf001c000 0x100>; + interrupts = <12 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&usart0_clk>; + clock-names = "usart"; + cs-gpios = <&pioB 3 0>; + }; diff --git a/include/dt-bindings/mfd/at91-usart.h b/include/dt-bindings/mfd/at91-usart.h new file mode 100644 index ..2de5bc312e1e --- /dev/null +++ b/include/dt-bindings/mfd/at91-usart.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * This header provides macros for AT91 USART DT bindings. + * + * Copyright (C) 2018 Microchip Technology + * + * Author: Radu Pirea + * + */ + +#ifndef __DT_BINDINGS_AT91_USART_H__ +#define __DT_BINDINGS_AT91_USART_H__ + +#define AT91_USART_MODE_SERIAL 0 +#define AT91_USART_MODE_SPI1 + +#endif /* __DT_BINDINGS_AT91_USART_H__ */ -- 2.17.1
Re: [PATCH v7 3/6] mfd: at91-usart: added mfd driver for usart
On 06/14/2018 10:58 AM, Ludovic Desroches wrote: On Wed, Jun 13, 2018 at 07:36:18PM +0300, Radu Pirea wrote: 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 Acked-by: Rob Herring Reviewed-by: Andy Shevchenko Acked-for-MFD-by: Lee Jones --- drivers/mfd/Kconfig | 9 ++ drivers/mfd/Makefile | 1 + drivers/mfd/at91-usart.c | 69 3 files changed, 79 insertions(+) create mode 100644 drivers/mfd/at91-usart.c diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b860eb5aa194..a886672b960d 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 d9d2cf0d32ef..db1332aa96db 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -185,6 +185,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 ..3014ce532644 --- /dev/null +++ b/drivers/mfd/at91-usart.c @@ -0,0 +1,69 @@ +// 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: + break; If there is an invalid opmode from the DT, you will pass a non initialized cell to mfd_add_device(). Regards Ludovic Hi Ludovic, Tnx. That's true. How is better to do if atmel,usart-mode has an invalid value? To initialize cell with at91_usart_serial_subdev or to print an error message and return -EINVAL? Regards. Radu Pirea + } + + 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_flexcom_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"); -- 2.17.1 ___ linux-arm-kernel mailing list linux-arm-ker...@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Re: [PATCH] mtd: spi-nor: add support for Microchip 25LC256
On 05/16/2018 04:47 PM, Marek Vasut wrote: On 05/16/2018 12:05 PM, Radu Pirea wrote: On Wed, 2018-05-16 at 00:17 +0200, Marek Vasut wrote: On 05/15/2018 06:22 PM, Radu Pirea wrote: On Fri, 2018-05-04 at 20:40 +0200, Boris Brezillon wrote: On Fri, 4 May 2018 18:54:04 +0300 Radu Pirea wrote: Added geometry description for Microchip 25LC256 memory. Same as for the dataflash stuff you posted a few weeks ago: I don't think this device belongs in the SPI NOR framework. Hi Boris, 25lc256 memory is similar with mr25h256, the only difference is the page size(64 vs 256). Because mr25h256 is already in SPI NOR framework I added here 25lc256. I think I must be reading the wrong datasheet, but can you show me how does it support things like READID opcode ? Hi Marek, I read the datasheet for 25lc256 and for mr25h256 and none of them supports READID. Is this required for a chip to be included in spi-nor framework? I just followed the mr25h256 as an example. So I thought until you pointed out the MR25 devices. Does the 25LC device need erase or not ? I think the MR25s didn't, but I might be wrong. You are right. MR25s does not need erase and the same thing is true for 25LC. Maybe the framework could support the 25LC afterall. Yes, this was my impression too. Thanks.
Re: [PATCH] mtd: spi-nor: add support for Microchip 25LC256
On 05/18/2018 01:03 PM, Marek Vasut wrote: On 05/18/2018 11:50 AM, Radu Pirea wrote: On 05/16/2018 04:47 PM, Marek Vasut wrote: On 05/16/2018 12:05 PM, Radu Pirea wrote: On Wed, 2018-05-16 at 00:17 +0200, Marek Vasut wrote: On 05/15/2018 06:22 PM, Radu Pirea wrote: On Fri, 2018-05-04 at 20:40 +0200, Boris Brezillon wrote: On Fri, 4 May 2018 18:54:04 +0300 Radu Pirea wrote: Added geometry description for Microchip 25LC256 memory. Same as for the dataflash stuff you posted a few weeks ago: I don't think this device belongs in the SPI NOR framework. Hi Boris, 25lc256 memory is similar with mr25h256, the only difference is the page size(64 vs 256). Because mr25h256 is already in SPI NOR framework I added here 25lc256. I think I must be reading the wrong datasheet, but can you show me how does it support things like READID opcode ? Hi Marek, I read the datasheet for 25lc256 and for mr25h256 and none of them supports READID. Is this required for a chip to be included in spi-nor framework? I just followed the mr25h256 as an example. So I thought until you pointed out the MR25 devices. Does the 25LC device need erase or not ? I think the MR25s didn't, but I might be wrong. You are right. MR25s does not need erase and the same thing is true for 25LC. Oh. And the command set is (except for readid) comparable to SPI NOR ? Maybe the framework could support the 25LC afterall. Yes, this was my impression too. I am still thinking that the AT25 driver might be a better fit for such devices. Can you take a look ? I tested the memory with at25 driver and it works with no line changed in driver. :)
Re: [PATCH v3 5/6] spi: at91-usart: add driver for at91-usart as spi
On 05/17/2018 08:04 AM, Mark Brown wrote: On Fri, May 11, 2018 at 01:38:21PM +0300, Radu Pirea wrote: +config SPI_AT91_USART +tristate "Atmel USART Controller as SPI" + depends on HAS_DMA + depends on (ARCH_AT91 || COMPILE_TEST) +select MFD_AT91_USART + help + This selects a driver for the AT91 USART Controller as SPI Master, + present on AT91 and SAMA5 SoC series. + This looks like there's some tab/space mixing going on here. +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for AT91 USART Controllers as SPI + * + * Copyright (C) 2018 Microchip Technology Inc. Make the entire block a C++ comment so it looks more intentional rather tha mixing C and C++. Hi Mark, I know it's ugly, but SPDX license identifier must be in a separate comment block. +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 (tx_buf && remaining) { + if (at91_usart_spi_tx_ready(aus)) + spi_writel(aus, THR, tx_buf[len - remaining]); + aus->current_tx_remaining_bytes--; Missing braces here - we only write to the FIFO if there's space but we unconditionally decrement the counter. Thanks. I will fix it. + } else { + if (at91_usart_spi_tx_ready(aus)) + spi_writel(aus, THR, US_DUMMY_TX); + } +} This looks like you're open coding SPI_CONTROLLER_MUST_TX + int len = aus->current_transfer->len; + int remaining = aus->current_rx_remaining_bytes; + u8 *rx_buf = aus->current_transfer->rx_buf; + + if (aus->current_rx_remaining_bytes) { + rx_buf[len - remaining] = spi_readb(aus, RHR); + aus->current_rx_remaining_bytes--; + } else { + spi_readb(aus, RHR); + } Similarly for _MUST_RX. + controller->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX; You're actually setting both flags... this means that the handling for cases with missing TX or RX buffers can't happen. Sorry. My mistake. I will remove unnecessary code.
[PATCH] spi-nor: Add support for Atmel Dataflash memories
This patch add support in spi-nor for allmost all dataflash memories supported by old mtd_dataflash driver. Signed-off-by: Radu Pirea --- drivers/mtd/spi-nor/spi-nor.c | 150 +- include/linux/mtd/spi-nor.h | 10 +++ 2 files changed, 158 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index d445a4d..4cb3cf7 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -89,6 +89,7 @@ struct flash_info { #define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */ #define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */ #define USE_CLSR BIT(14) /* use CLSR command */ +#define SPI_DATAFLASH BIT(15) /* Atmel Dataflash memory */ int (*quad_enable)(struct spi_nor *nor); }; @@ -306,6 +307,20 @@ static int s3an_sr_ready(struct spi_nor *nor) return !!(val & XSR_RDY); } +static int dataflash_sr_ready(struct spi_nor *nor) +{ + int ret; + u8 val; + + ret = nor->read_reg(nor, SPINOR_OP_DFRDSR, &val, 1); + if (ret < 0) { + dev_err(nor->dev, "error %d reading DFSR\n", ret); + return ret; + } + + return !!(val & DFSR_RDY); +} + static inline int spi_nor_sr_ready(struct spi_nor *nor) { int sr = read_sr(nor); @@ -354,6 +369,8 @@ static int spi_nor_ready(struct spi_nor *nor) if (nor->flags & SNOR_F_READY_XSR_RDY) sr = s3an_sr_ready(nor); + else if (nor->flags & SPI_DATAFLASH) + sr = dataflash_sr_ready(nor); else sr = spi_nor_sr_ready(nor); if (sr < 0) @@ -457,6 +474,44 @@ static loff_t spi_nor_s3an_addr_convert(struct spi_nor *nor, unsigned int addr) return page | offset; } +static loff_t spi_nor_dataflash_addr_convert(struct spi_nor *nor, +unsigned int addr) +{ + unsigned int offset; + unsigned int page; + unsigned int page_offset; + + page = addr / nor->page_size; + offset = addr % nor->page_size; + page_offset = fls(nor->page_size); + if (is_power_of_2(nor->page_size)) + page_offset--; + + return (page << page_offset) | offset; +} + +static int spi_nor_dataflash_erase_sector(struct spi_nor *nor, u32 addr) +{ + u32 block_size = 8 * nor->page_size; + u32 blocks = nor->mtd.erasesize / block_size; + u32 addr_local; + u8 buf[SPI_NOR_MAX_ADDR_WIDTH]; + int i, j; + + for (j = 0; j < blocks; j++) { + addr_local = spi_nor_dataflash_addr_convert(nor, addr); + for (i = nor->addr_width - 1; i >= 0; i--) { + buf[i] = addr_local & 0xff; + addr_local >>= 8; + } + nor->write_reg(nor, nor->erase_opcode, buf, nor->addr_width); + addr += block_size; + spi_nor_wait_till_ready(nor); + } + + return 0; +} + /* * Initiate the erasure of a single sector */ @@ -542,7 +597,11 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) while (len) { write_enable(nor); - ret = spi_nor_erase_sector(nor, addr); + if (nor->flags & SPI_DATAFLASH) + ret = spi_nor_dataflash_erase_sector(nor, addr); + else + ret = spi_nor_erase_sector(nor, addr); + if (ret) goto erase_err; @@ -914,6 +973,20 @@ static int macronix_quad_enable(struct spi_nor *nor); .page_size = 256, \ .flags = (_flags), +#define INFOP(_jedec_id, _ext_id, _sector_size, _n_sectors, _page_size, _flags)\ + .id = { \ + ((_jedec_id) >> 16) & 0xff, \ + ((_jedec_id) >> 8) & 0xff, \ + (_jedec_id) & 0xff, \ + ((_ext_id) >> 8) & 0xff,\ + (_ext_id) & 0xff, \ + }, \ + .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))), \ + .sector_size = (_sector_size), \ + .n_sectors = (_n_sectors), \ + .page_size = _page_size,\ + .flags = (_flags), + #define INFO6(_jedec_id, _ext_id, _se
Re: [PATCH v4 6/6] tty/serial: atmel: changed the driver to work under at91-usart mfd
On 05/28/2018 01:08 PM, Richard Genoud wrote: On 25/05/2018 19:19, Radu Pirea wrote: This patch modifies the place where resources and device tree properties are searched. Signed-off-by: Radu Pirea --- drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 40 +-- 2 files changed, 23 insertions(+), 18 deletions(-) the stdout-path property of the chosen node is still broken in this verion. if : stdout-path = "serial0:115200n8"; is set in the DTS, the console output should go on serial0 (aka dbgu) cf Documentation/devicetree/bindings/chosen.txt With this patch applied, this is not the case anymore. Adding console=ttyS0,115200 in the chosen node is not the solution here. I fixed the issue few minutes ago :) I hope DMA setup is ok now. regards, Richard.
Re: [PATCH v4 5/6] spi: at91-usart: add driver for at91-usart as spi
On 05/28/2018 11:21 AM, Andy Shevchenko wrote: On Fri, May 25, 2018 at 8:19 PM, Radu Pirea wrote: 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. +#include What is the use of it? I need of_gpio.h for of_gpio_named_count, of_get_named_gpio and devm_gpio_request_one(found in gpio.h) +#define US_INIT(US_MR_SPI_MASTER | US_MR_CHRL | US_MR_CLKO | \ + US_MR_WRDBT) Don't split lines like this, it's hard to read. #define FOO \ (BAR1 | BAR2) I'll fix it. I think I already told this to someone recently, maybe to you. +/* Register access macros */ +#define spi_readl(port, reg) \ + readl_relaxed((port)->regs + US_##reg) +#define spi_writel(port, reg, value) \ + writel_relaxed((value), (port)->regs + US_##reg) + +#define spi_readb(port, reg) \ + readb_relaxed((port)->regs + US_##reg) +#define spi_writeb(port, reg, value) \ + writeb_relaxed((value), (port)->regs + US_##reg) Names are too generic. You better to use the same prefix as for the rest, i.e. at91_spi_ Good ideea. I will change the names. + /*used in interrupt to protect data reading*/ Comment style. You need to read some existing code, perhaps, to see how it's done. Ok. I will add the comment. +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) + if (at91_usart_spi_tx_ready(aus)) { if (x) { if (y) { ... } } is equivalent to if (x && y) {}. Though, considering your intention here, I would rather go with better pattern, i.e. if (!remaining) return; Thank for suggestion. I will change. + 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) +{ + if (remaining) { + rx_buf[len - remaining] = spi_readb(aus, RHR); + aus->current_rx_remaining_bytes--; + } Ditto. +} +static int at91_usart_gpio_setup(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.parent->of_node; Your driver is not OF specific as far as I can see. Drop all these device_node stuff and change API calls respectively. Ok. What do you suggest to use instead of OF API to get the count of cs-gpios and to read their values one by one? + int i; + int ret = 0; + int nb = 0; What happened to indentation? Redundnant assignment for both. + 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) +{ + regs = platform_get_resource(to_platform_device(pdev->dev.parent), +IORESOURCE_MEM, 0); + if (!regs) + return -EINVAL; This looks weird. Supply resource to _this_ device in your MFD code. I know weird, but is the safest way to pass the resource and the of_node. + dev_info(&pdev->dev, +"Atmel USART SPI Controller version 0x%x at 0x%08lx (irq %d)\n", +spi_readl(aus, VERSION), +(unsigned long)regs->start, irq); I think I already told you, don't use explicit casting when print. If it wasn't you, do you homework then. But above is no go. > + return 0; +static struct platform_driver at91_usart_spi_driver = { + .driver = { + .name = "at91_usart_spi", + .of_match_table = of_match_ptr(at91_usart_spi_dt_ids), Drop of_match_ptr(). It's not needed. + }, + .probe = at91_usart_spi_probe, + .remove = at91_usart_spi_remove, }; Already told ya, split lines correctly.
[PATCH v5 0/6] Driver for at91 usart in spi mode
Hello, This is the second version of driver. I added a mfd driver which by default probes atmel_serial driver and if in dt is specified to probe the spi driver, then the spi-at91-usart driver will be probed. The compatible for atmel_serial is now the compatible for at91-usart mfd driver and compatilbe for atmel_serial driver was changed in order to keep the bindings for serial as they are. Changes in v1: - added spi-at91-usart driver Changes in v2: - added at91-usart mfd driver - modified spi-at91-usart driver to work as mfd driver child - modified atmel_serial driver to work as mfd driver child Changes in v3: - fixed spi slaves probing Changes in v4: - modified the spi driver to use cs gpio support form spi subsystem - fixed dma transfers for serial driver - squashed binding for spi and serial and moved them to mfd/atmel-usart.txt Changes in v5: - fixed usage of stdout-path property with atmel_serial driver Radu Pirea (6): MAINTAINERS: add at91 usart mfd driver dt-bindings: add binding for atmel-usart in SPI mode mfd: at91-usart: added mfd driver for usart MAINTAINERS: add at91 usart spi driver spi: at91-usart: add driver for at91-usart as spi tty/serial: atmel: changed the driver to work under at91-usart mfd .../bindings/{serial => mfd}/atmel-usart.txt | 25 +- MAINTAINERS | 16 + drivers/mfd/Kconfig | 9 + drivers/mfd/Makefile | 1 + drivers/mfd/at91-usart.c | 67 +++ drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 436 ++ drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 41 +- include/dt-bindings/mfd/at91-usart.h | 17 + 11 files changed, 604 insertions(+), 19 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) create mode 100644 drivers/mfd/at91-usart.c create mode 100644 drivers/spi/spi-at91-usart.c create mode 100644 include/dt-bindings/mfd/at91-usart.h -- 2.17.1
[PATCH v5 1/6] MAINTAINERS: add at91 usart mfd driver
Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea --- MAINTAINERS | 9 + 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 8e2a2fddbd19..12203d07c6af 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9160,6 +9160,7 @@ M:Richard Genoud S: Maintained F: drivers/tty/serial/atmel_serial.c F: drivers/tty/serial/atmel_serial.h +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt MICROCHIP / ATMEL DMA DRIVER M: Ludovic Desroches @@ -9192,6 +9193,14 @@ S: Supported F: drivers/mtd/nand/raw/atmel/* F: Documentation/devicetree/bindings/mtd/atmel-nand.txt +MICROCHIP AT91 USART MFD DRIVER +M: Radu Pirea +L: linux-kernel@vger.kernel.org +S: Supported +F: drivers/mfd/at91-usart.c +F: include/dt-bindings/mfd/at91-usart.h +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.17.1
[PATCH v5 3/6] mfd: at91-usart: added 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 Acked-by: Rob Herring --- drivers/mfd/Kconfig | 9 ++ drivers/mfd/Makefile | 1 + drivers/mfd/at91-usart.c | 67 3 files changed, 77 insertions(+) create mode 100644 drivers/mfd/at91-usart.c diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b860eb5aa194..a886672b960d 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 d9d2cf0d32ef..db1332aa96db 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -185,6 +185,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 ..262e7affba22 --- /dev/null +++ b/drivers/mfd/at91-usart.c @@ -0,0 +1,67 @@ +// 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; + int err; + + err = 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: + default: + cell = at91_usart_serial_subdev; + } + + 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_flexcom_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"); -- 2.17.1
[PATCH v5 6/6] tty/serial: atmel: changed 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 --- drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 41 ++- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 3682fd3e960c..25e55332f8b1 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -119,6 +119,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 df46a9e88c34..5c74e03396ef 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -193,8 +193,8 @@ 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" }, + { .compatible = "atmel,at91sam9260-usart-serial" }, { /* sentinel */ } }; #endif @@ -915,6 +915,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 +923,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 +1094,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 +1106,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", @@ -1631,7 +1633,7 @@ static void atmel_tasklet_tx_func(unsigned long data) static void atmel_init_property(struct atmel_uart_port *atmel_port, struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; + struct device_node *np = pdev->dev.parent->of_node; /* DMA/PDC usage specification */ if (of_property_read_bool(np, "atmel,use-dma-rx")) { @@ -,8 +2224,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 +2240,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 +2343,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_g
[PATCH v5 5/6] 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 --- drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 436 +++ 3 files changed, 446 insertions(+) create mode 100644 drivers/spi/spi-at91-usart.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 6fb0347a24f2..1a002a32d7aa 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -77,6 +77,15 @@ 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 HAS_DMA + depends on (ARCH_AT91 || COMPILE_TEST) + select 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 34c5f2832ddf..fb6cb42f4eaa 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -15,6 +15,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 ..be7495527c72 --- /dev/null +++ b/drivers/spi/spi-at91-usart.c @@ -0,0 +1,436 @@ +// 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_BRGR0x20 +#define US_VERSION 0xFC + +#define US_CR_RSTRXBIT(2) +#define US_CR_RSTTXBIT(3) +#define US_CR_RXEN BIT(4) +#define US_CR_RXDISBIT(5) +#define US_CR_TXEN BIT(6) +#define US_CR_TXDISBIT(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_WRDBTBIT(20) +#define US_MR_LOOP BIT(15) + +#define US_IR_RXRDYBIT(0) +#define US_IR_TXRDYBIT(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 intcurrent_tx_remaining_bytes; + unsigned intcurrent_rx_remaining_bytes; + int done_status; + + u32 spi_clk; + u32 status; + + boolxfer_failed; +}; + +static inline u32 at91_usart_spi_tx_ready(struct at91_usart_spi *aus) +{ + return aus->status & US_IR_TXRDY; +} + +static in
[PATCH v5 4/6] MAINTAINERS: add at91 usart spi driver
Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea --- MAINTAINERS | 7 +++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 12203d07c6af..dae31df711fb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9201,6 +9201,13 @@ F: drivers/mfd/at91-usart.c F: include/dt-bindings/mfd/at91-usart.h F: Documentation/devicetree/bindings/mfd/atmel-usart.txt +MICROCHIP AT91 USART SPI DRIVER +M: Radu Pirea +L: linux-...@vger.kernel.org +S: Supported +F: drivers/spi/spi-at91-usart.c +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.17.1
[PATCH v5 2/6] dt-bindings: add binding for atmel-usart in SPI mode
This patch moves the bindings for serial from serial/atmel-usart.txt to mfd/atmel-usart.txt and adds bindings for USART in SPI mode. Signed-off-by: Radu Pirea Reviewed-by: Rob Herring --- .../bindings/{serial => mfd}/atmel-usart.txt | 25 +-- include/dt-bindings/mfd/at91-usart.h | 17 + 2 files changed, 40 insertions(+), 2 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) create mode 100644 include/dt-bindings/mfd/at91-usart.h diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/mfd/atmel-usart.txt similarity index 76% rename from Documentation/devicetree/bindings/serial/atmel-usart.txt rename to Documentation/devicetree/bindings/mfd/atmel-usart.txt index 7c0d6b2f53e4..3b9e18642c3b 100644 --- a/Documentation/devicetree/bindings/serial/atmel-usart.txt +++ b/Documentation/devicetree/bindings/mfd/atmel-usart.txt @@ -1,6 +1,6 @@ * Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART) -Required properties: +Required properties for USART: - compatible: Should be "atmel,-usart" or "atmel,-dbgu" The compatible indicated will be the first SoC to support an additional mode or an USART new feature. @@ -11,7 +11,13 @@ Required properties: Required elements: "usart" - clocks: phandles to input clocks. -Optional properties: +Required properties for USART in SPI mode: +- #size-cells : Must be <0> +- #address-cells : Must be <1> +- cs-gpios: chipselects (internal cs not supported) +- atmel,usart-mode : Must be (found in dt-bindings/mfd/at91-usart.h) + +Optional properties in serial mode: - atmel,use-dma-rx: use of PDC or DMA for receiving data - atmel,use-dma-tx: use of PDC or DMA for transmitting data - {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD line respectively. @@ -62,3 +68,18 @@ Example: dma-names = "tx", "rx"; atmel,fifo-size = <32>; }; + +- SPI mode: + #include + + spi0: spi@f001c000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "atmel,at91rm9200-usart", "atmel,at91sam9260-usart"; + atmel,usart-mode = ; + reg = <0xf001c000 0x100>; + interrupts = <12 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&usart0_clk>; + clock-names = "usart"; + cs-gpios = <&pioB 3 0>; + }; diff --git a/include/dt-bindings/mfd/at91-usart.h b/include/dt-bindings/mfd/at91-usart.h new file mode 100644 index ..ac811628a42d --- /dev/null +++ b/include/dt-bindings/mfd/at91-usart.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * This header provides macros for AT91 USART DT bindings. + * + * Copyright (C) 2018 Microchip Technology + * + * Author: Radu Pirea + * + */ + +#ifndef __DT_BINDINGS_AT91_USART_H__ +#define __DT_BINDINGS_AT91_USART_H__ + +#define AT91_USART_MODE_SERIAL 1 +#define AT91_USART_MODE_SPI2 + +#endif /* __DT_BINDINGS_AT91_USART_H__ */ -- 2.17.1
[PATCH v6 1/6] MAINTAINERS: add at91 usart mfd driver
Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea --- MAINTAINERS | 9 + 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 8e2a2fddbd19..12203d07c6af 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9160,6 +9160,7 @@ M:Richard Genoud S: Maintained F: drivers/tty/serial/atmel_serial.c F: drivers/tty/serial/atmel_serial.h +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt MICROCHIP / ATMEL DMA DRIVER M: Ludovic Desroches @@ -9192,6 +9193,14 @@ S: Supported F: drivers/mtd/nand/raw/atmel/* F: Documentation/devicetree/bindings/mtd/atmel-nand.txt +MICROCHIP AT91 USART MFD DRIVER +M: Radu Pirea +L: linux-kernel@vger.kernel.org +S: Supported +F: drivers/mfd/at91-usart.c +F: include/dt-bindings/mfd/at91-usart.h +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.17.1
[PATCH v6 3/6] mfd: at91-usart: added 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 Acked-by: Rob Herring --- drivers/mfd/Kconfig | 9 ++ drivers/mfd/Makefile | 1 + drivers/mfd/at91-usart.c | 68 3 files changed, 78 insertions(+) create mode 100644 drivers/mfd/at91-usart.c diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b860eb5aa194..a886672b960d 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 d9d2cf0d32ef..db1332aa96db 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -185,6 +185,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 ..1a2bdeff7f6d --- /dev/null +++ b/drivers/mfd/at91-usart.c @@ -0,0 +1,68 @@ +// 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; + int err; + + err = 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: + default: + cell = at91_usart_serial_subdev; + } + + 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_flexcom_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"); -- 2.17.1
[PATCH v6 6/6] 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 --- drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 42 --- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 3682fd3e960c..25e55332f8b1 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -119,6 +119,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 df46a9e88c34..5ef8a6a6fe17 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", @@ -,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
[PATCH v6 4/6] MAINTAINERS: add at91 usart spi driver
Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea --- MAINTAINERS | 7 +++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 12203d07c6af..dae31df711fb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9201,6 +9201,13 @@ F: drivers/mfd/at91-usart.c F: include/dt-bindings/mfd/at91-usart.h F: Documentation/devicetree/bindings/mfd/atmel-usart.txt +MICROCHIP AT91 USART SPI DRIVER +M: Radu Pirea +L: linux-...@vger.kernel.org +S: Supported +F: drivers/spi/spi-at91-usart.c +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.17.1
[PATCH v6 0/6] Driver for at91 usart in spi mode
Hello, This is the second version of driver. I added a mfd driver which by default probes atmel_serial driver and if in dt is specified to probe the spi driver, then the spi-at91-usart driver will be probed. The compatible for atmel_serial is now the compatible for at91-usart mfd driver and compatilbe for atmel_serial driver was changed in order to keep the bindings for serial as they are. Changes in v1: - added spi-at91-usart driver Changes in v2: - added at91-usart mfd driver - modified spi-at91-usart driver to work as mfd driver child - modified atmel_serial driver to work as mfd driver child Changes in v3: - fixed spi slaves probing Changes in v4: - modified the spi driver to use cs gpio support form spi subsystem - fixed dma transfers for serial driver - squashed binding for spi and serial and moved them to mfd/atmel-usart.txt Changes in v5: - fixed usage of stdout-path property with atmel_serial driver Changes in v6: - removed unused compatible strings from serial and spi drivers Radu Pirea (6): MAINTAINERS: add at91 usart mfd driver dt-bindings: add binding for atmel-usart in SPI mode mfd: at91-usart: added mfd driver for usart MAINTAINERS: add at91 usart spi driver spi: at91-usart: add driver for at91-usart as spi tty/serial: atmel: change the driver to work under at91-usart mfd .../bindings/{serial => mfd}/atmel-usart.txt | 25 +- MAINTAINERS | 16 + drivers/mfd/Kconfig | 9 + drivers/mfd/Makefile | 1 + drivers/mfd/at91-usart.c | 68 +++ drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 434 ++ drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 42 +- include/dt-bindings/mfd/at91-usart.h | 17 + 11 files changed, 606 insertions(+), 17 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) create mode 100644 drivers/mfd/at91-usart.c create mode 100644 drivers/spi/spi-at91-usart.c create mode 100644 include/dt-bindings/mfd/at91-usart.h -- 2.17.1
[PATCH v6 5/6] 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 --- drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 434 +++ 3 files changed, 444 insertions(+) create mode 100644 drivers/spi/spi-at91-usart.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 6fb0347a24f2..1a002a32d7aa 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -77,6 +77,15 @@ 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 HAS_DMA + depends on (ARCH_AT91 || COMPILE_TEST) + select 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 34c5f2832ddf..fb6cb42f4eaa 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -15,6 +15,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 ..ae889aa6bda3 --- /dev/null +++ b/drivers/spi/spi-at91-usart.c @@ -0,0 +1,434 @@ +// 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_BRGR0x20 +#define US_VERSION 0xFC + +#define US_CR_RSTRXBIT(2) +#define US_CR_RSTTXBIT(3) +#define US_CR_RXEN BIT(4) +#define US_CR_RXDISBIT(5) +#define US_CR_TXEN BIT(6) +#define US_CR_TXDISBIT(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_WRDBTBIT(20) +#define US_MR_LOOP BIT(15) + +#define US_IR_RXRDYBIT(0) +#define US_IR_TXRDYBIT(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 intcurrent_tx_remaining_bytes; + unsigned intcurrent_rx_remaining_bytes; + int done_status; + + u32 spi_clk; + u32 status; + + boolxfer_failed; +}; + +static inline u32 at91_usart_spi_tx_ready(struct at91_usart_spi *aus) +{ + return aus->status & US_IR_TXRDY; +} + +static in
[PATCH v6 2/6] dt-bindings: add binding for atmel-usart in SPI mode
This patch moves the bindings for serial from serial/atmel-usart.txt to mfd/atmel-usart.txt and adds bindings for USART in SPI mode. Signed-off-by: Radu Pirea Reviewed-by: Rob Herring --- .../bindings/{serial => mfd}/atmel-usart.txt | 25 +-- include/dt-bindings/mfd/at91-usart.h | 17 + 2 files changed, 40 insertions(+), 2 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) create mode 100644 include/dt-bindings/mfd/at91-usart.h diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/mfd/atmel-usart.txt similarity index 76% rename from Documentation/devicetree/bindings/serial/atmel-usart.txt rename to Documentation/devicetree/bindings/mfd/atmel-usart.txt index 7c0d6b2f53e4..3b9e18642c3b 100644 --- a/Documentation/devicetree/bindings/serial/atmel-usart.txt +++ b/Documentation/devicetree/bindings/mfd/atmel-usart.txt @@ -1,6 +1,6 @@ * Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART) -Required properties: +Required properties for USART: - compatible: Should be "atmel,-usart" or "atmel,-dbgu" The compatible indicated will be the first SoC to support an additional mode or an USART new feature. @@ -11,7 +11,13 @@ Required properties: Required elements: "usart" - clocks: phandles to input clocks. -Optional properties: +Required properties for USART in SPI mode: +- #size-cells : Must be <0> +- #address-cells : Must be <1> +- cs-gpios: chipselects (internal cs not supported) +- atmel,usart-mode : Must be (found in dt-bindings/mfd/at91-usart.h) + +Optional properties in serial mode: - atmel,use-dma-rx: use of PDC or DMA for receiving data - atmel,use-dma-tx: use of PDC or DMA for transmitting data - {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD line respectively. @@ -62,3 +68,18 @@ Example: dma-names = "tx", "rx"; atmel,fifo-size = <32>; }; + +- SPI mode: + #include + + spi0: spi@f001c000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "atmel,at91rm9200-usart", "atmel,at91sam9260-usart"; + atmel,usart-mode = ; + reg = <0xf001c000 0x100>; + interrupts = <12 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&usart0_clk>; + clock-names = "usart"; + cs-gpios = <&pioB 3 0>; + }; diff --git a/include/dt-bindings/mfd/at91-usart.h b/include/dt-bindings/mfd/at91-usart.h new file mode 100644 index ..ac811628a42d --- /dev/null +++ b/include/dt-bindings/mfd/at91-usart.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * This header provides macros for AT91 USART DT bindings. + * + * Copyright (C) 2018 Microchip Technology + * + * Author: Radu Pirea + * + */ + +#ifndef __DT_BINDINGS_AT91_USART_H__ +#define __DT_BINDINGS_AT91_USART_H__ + +#define AT91_USART_MODE_SERIAL 1 +#define AT91_USART_MODE_SPI2 + +#endif /* __DT_BINDINGS_AT91_USART_H__ */ -- 2.17.1
Re: [PATCH v3 5/6] spi: at91-usart: add driver for at91-usart as spi
On Mon, 2018-05-14 at 20:38 +0300, Andy Shevchenko wrote: > First of all, do not remove mailing lists from Cc and people if you > are not sure they do not need your stuff. > Sorry. My mistake. > On Mon, May 14, 2018 at 11:11 AM, Radu Pirea > wrote: > > On Sun, 2018-05-13 at 16:33 +0300, Andy Shevchenko wrote: > > > On Fri, May 11, 2018 at 1:38 PM, Radu Pirea > > .com > > > > wrote: > > > > +static void at91_usart_spi_cleanup(struct spi_device *spi) > > > > +{ > > > > + struct at91_usart_spi_device *ausd = spi- > > > > >controller_state; > > > > + > > > > + if (!ausd) > > > > + return; > > > > > > Is it even possible? > > > > Theoretically yes. > > I would like to know real circumstances when it might happen. That check was used in debug stage of driver. I will remove. > > > > > > > Anyway the code below will work fine even if it's the case. > > > > > > > + > > > > + spi->controller_state = NULL; > > > > + kfree(ausd); > > > > +} > > > The question is, why you didn't utilize what SPI core provides > > > you? > > > > I tried, but it did not work the way I expected. > > So, what is not going as expected in "SPI core takes care of CSs" > case? > Did you use oscilloscope for that? Yes, I used and CSs was not asserted. Anyway, I will will try again. >
Re: [PATCH v3 5/6] spi: at91-usart: add driver for at91-usart as spi
On Sun, 2018-05-13 at 16:33 +0300, Andy Shevchenko wrote: > On Fri, May 11, 2018 at 1:38 PM, Radu Pirea > wrote: > > 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. > > +#include > > +#include > > Here is something wrong. You need to use latter one in new code. > > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > Hmm... Do you need all of them? > > > +static inline void at91_usart_spi_cs_activate(struct spi_device > > *spi) > > +{ > > ... > > + gpiod_set_value(ausd->npcs_pin, active); > > + aus->cs_active = true; > > +} > > + > > +static inline void at91_usart_spi_cs_deactivate(struct spi_device > > *spi) > > +{ > > ... > > + gpiod_set_value(ausd->npcs_pin, !active); > > + aus->cs_active = false; > > +} > > ... > > + if (!ausd) { > > + if (gpio_is_valid(spi->cs_gpio)) { > > + npcs_pin = gpio_to_desc(spi->cs_gpio); > > ... > > + } > > ... > > + gpiod_direction_output(npcs_pin, !(spi->mode & > > SPI_CS_HIGH)); > > + > > + ausd->npcs_pin = npcs_pin; > > ... > > + } > > I will refer to above as (1) later on. > > > + dev_dbg(&spi->dev, "new message %p submitted for %s\n", > > + msg, dev_name(&spi->dev)); > > %p does make a very little sense. > > > + list_for_each_entry(xfer, &msg->transfers, transfer_list) { > > + ret = at91_usart_spi_one_transfer(controller, msg, > > xfer); > > + if (ret) > > + goto msg_done; > > + } > > Cant SPI core do this for your? > > > +static void at91_usart_spi_cleanup(struct spi_device *spi) > > +{ > > + struct at91_usart_spi_device *ausd = spi->controller_state; > > + > > + if (!ausd) > > + return; > > Is it even possible? > > Anyway the code below will work fine even if it's the case. > > > + > > + spi->controller_state = NULL; > > + kfree(ausd); > > +} > > +static int at91_usart_spi_gpio_cs(struct platform_device *pdev) > > +{ > > + struct spi_controller *controller = > > platform_get_drvdata(pdev); > > + struct device_node *np = controller->dev.parent->of_node; > > + struct gpio_desc *cs_gpio; > > + int nb; > > + int i; > > + > > + if (!np) > > + return 0; > > + > > + nb = of_gpio_named_count(np, "cs-gpios"); > > + for (i = 0; i < nb; i++) { > > + cs_gpio = devm_gpiod_get_from_of_node(&pdev->dev, > > + pdev- > > >dev.parent->of_node, > > + "cs-gpios", > > + i, > > GPIOD_OUT_HIGH, > > + dev_name(&pde > > v->dev)); > > + if (IS_ERR(cs_gpio)) > > + return PTR_ERR(cs_gpio); > > + } > > + > > + controller->num_chipselect = nb; > > + > > + return 0; > > +} > > The question is, why you didn't utilize what SPI core provides you? > > > + spi_writel(aus, MR, US_MR_SPI_MASTER | US_MR_CHRL | > > US_MR_CLKO | > > + US_MR_WRDBT); > > + spi_writel(aus, CR, US_CR_RXDIS | US_CR_TXDIS | US_CR_RSTRX > > | > > + US_CR_RSTTX); > > I didn't check over, but it seems like you might have duplication in > these bitwise ORs. Consider to unify them into another (shorter) > definitions and reuse all over the code. > > > + regs = platform_get_resource(to_platform_device(pdev- > > >dev.parent), > > +IORESOURCE_MEM, 0); > > + if (!regs) > > + return -ENXIO; > > Strange error code for getting MMIO resource. ENOMEM sounds better. > > > + dev_info(&pdev->dev, > > +"Atmel USART SPI Controller version 0x%x at > > 0x%08lx (irq %d)\n", > > +spi_readl(aus, VERSION), > > +(unsigned long)regs->start, irq); > > If you do explicit casting when printing something you are doing > wrong. > Please use %pR or %pr in this case. > > > +static struct platform_driver at91_usart_spi_driver = { > > + .driver = { > > + .name = "at91_usart_spi", > > + .of_match_table = > > of_match_ptr(at91_usart_spi_dt_ids), > > Can it work as pure platform driver? If no, of_match_ptr() is > redundant. This driver can not work as pure platform driver, but I the way I used to probe it from MFD(by compatbile string). Do you know another way? > > > + }, > > + .probe = at91_usart_spi_probe, > > + .remove = at91_usart_spi_remove, }; > > Two lines at one. Split. >
Re: [PATCH v3 6/6] tty/serial: atmel: changed the driver to work under at91-usart mfd
On Mon, 2018-05-14 at 12:57 +0200, Richard Genoud wrote: > Hi, > > On 11/05/2018 12:38, Radu Pirea wrote: > > This patch modifies the place where resources and device tree > > properties > > are searched. > > > > Signed-off-by: Radu Pirea > > --- > > drivers/tty/serial/Kconfig| 1 + > > drivers/tty/serial/atmel_serial.c | 29 +++-- > > > > 2 files changed, 16 insertions(+), 14 deletions(-) > > > > diff --git a/drivers/tty/serial/Kconfig > > b/drivers/tty/serial/Kconfig > > index 3682fd3e960c..25e55332f8b1 100644 > > --- a/drivers/tty/serial/Kconfig > > +++ b/drivers/tty/serial/Kconfig > > @@ -119,6 +119,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 df46a9e88c34..6b4494352853 100644 > > --- a/drivers/tty/serial/atmel_serial.c > > +++ b/drivers/tty/serial/atmel_serial.c > > @@ -193,8 +193,8 @@ 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" }, > > + { .compatible = "atmel,at91sam9260-usart-serial" }, > > { /* sentinel */ } > > }; > > #endif > > @@ -1631,7 +1631,7 @@ static void atmel_tasklet_tx_func(unsigned > > long data) > > static void atmel_init_property(struct atmel_uart_port > > *atmel_port, > > struct platform_device *pdev) > > { > > - struct device_node *np = pdev->dev.of_node; > > + struct device_node *np = pdev->dev.parent->of_node; > > > > /* DMA/PDC usage specification */ > > if (of_property_read_bool(np, "atmel,use-dma-rx")) { > > @@ -2223,7 +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; > > + int size = to_platform_device(pdev->dev.parent)- > > >resource[0].end - > > + to_platform_device(pdev->dev.parent)- > > >resource[0].start + 1; > > I think it may be simpler with something like: > + struct platform_device *mfd_pdev = to_platform_device(port- > >dev->parent); > + int size = mfd_pdev->resource[0].end - mfd_pdev- > >resource[0].start + 1; > > > > > release_mem_region(port->mapbase, size); > > > > @@ -2239,7 +2240,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; > > + int size = to_platform_device(pdev->dev.parent)- > > >resource[0].end - > > + to_platform_device(pdev->dev.parent)- > > >resource[0].start + 1; > > > > ditto > > > if (!request_mem_region(port->mapbase, size, > > "atmel_serial")) > > return -EBUSY; > > @@ -2345,23 +2347,23 @@ static int atmel_init_port(struct > > atmel_uart_port *atmel_port, > > Here, we could also add: > + struct device *mfd_dev = pdev->dev.parent; > + struct platform_device *mfd_pdev = > to_platform_device(mfd_dev); > > > atmel_init_property(atmel_port, pdev); > > atmel_set_ops(port); > > > > - uart_get_rs485_mode(&pdev->dev, &port->rs485); > > + uart_get_rs485_mode(pdev->dev.parent, &port->rs485); > > ...and use them here > > > > > 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].st
Re: [PATCH] mtd: spi-nor: add support for Microchip 25LC256
On Fri, 2018-05-04 at 20:40 +0200, Boris Brezillon wrote: > On Fri, 4 May 2018 18:54:04 +0300 > Radu Pirea wrote: > > > Added geometry description for Microchip 25LC256 memory. > > Same as for the dataflash stuff you posted a few weeks ago: I don't > think this device belongs in the SPI NOR framework. Hi Boris, 25lc256 memory is similar with mr25h256, the only difference is the page size(64 vs 256). Because mr25h256 is already in SPI NOR framework I added here 25lc256. > > > > Signed-off-by: Radu Pirea > > --- > > drivers/mtd/devices/m25p80.c | 3 +++ > > drivers/mtd/spi-nor/spi-nor.c | 3 +++ > > 2 files changed, 6 insertions(+) > > > > diff --git a/drivers/mtd/devices/m25p80.c > > b/drivers/mtd/devices/m25p80.c > > index a4e18f6aaa33..1e359d811261 100644 > > --- a/drivers/mtd/devices/m25p80.c > > +++ b/drivers/mtd/devices/m25p80.c > > @@ -372,6 +372,9 @@ static const struct spi_device_id m25p_ids[] = > > { > > { "mr25h10" }, /* 1 Mib, 40 MHz */ > > { "mr25h40" }, /* 4 Mib, 40 MHz */ > > > > + /* Microchip */ > > + { "25lc256" }, > > + > > { }, > > }; > > MODULE_DEVICE_TABLE(spi, m25p_ids); > > diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi- > > nor/spi-nor.c > > index d445a4d3b770..6341c86be647 100644 > > --- a/drivers/mtd/spi-nor/spi-nor.c > > +++ b/drivers/mtd/spi-nor/spi-nor.c > > @@ -1076,6 +1076,9 @@ static const struct flash_info spi_nor_ids[] > > = { > > { "mx66l1g45g", INFO(0xc2201b, 0, 64 * 1024, 2048, > > SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, > > { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, > > SPI_NOR_QUAD_READ) }, > > > > + /* Microchip */ > > + { "25lc256", CAT25_INFO(32 * 1024, 1, 64, 2, > > SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, > > + > > /* Micron */ > > { "n25q016a",INFO(0x20bb15, 0, 64 * 1024, 32, > > SECT_4K | SPI_NOR_QUAD_READ) }, > > { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, > > SPI_NOR_QUAD_READ) }, > > signature.asc Description: This is a digitally signed message part
Re: [PATCH] mtd: spi-nor: add support for Microchip 25LC256
On Wed, 2018-05-16 at 00:17 +0200, Marek Vasut wrote: > On 05/15/2018 06:22 PM, Radu Pirea wrote: > > On Fri, 2018-05-04 at 20:40 +0200, Boris Brezillon wrote: > > > On Fri, 4 May 2018 18:54:04 +0300 > > > Radu Pirea wrote: > > > > > > > Added geometry description for Microchip 25LC256 memory. > > > > > > Same as for the dataflash stuff you posted a few weeks ago: I > > > don't > > > think this device belongs in the SPI NOR framework. > > > > Hi Boris, > > > > 25lc256 memory is similar with mr25h256, the only difference is the > > page size(64 vs 256). Because mr25h256 is already in SPI NOR > > framework > > I added here 25lc256. > > I think I must be reading the wrong datasheet, but can you show me > how > does it support things like READID opcode ? > Hi Marek, I read the datasheet for 25lc256 and for mr25h256 and none of them supports READID. Is this required for a chip to be included in spi-nor framework? I just followed the mr25h256 as an example. signature.asc Description: This is a digitally signed message part
[PATCH v2 2/2] spi: at91-usart: add DMA support
This patch adds support for DMA. Transfers are done with dma only if they are longer than 16 bytes in order to achieve a better performance. DMA setup introduces a little overhead and for transfers shorter than 16 bytes there is no performance improvement. Signed-off-by: Radu Pirea --- drivers/spi/spi-at91-usart.c | 221 ++- 1 file changed, 219 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-at91-usart.c b/drivers/spi/spi-at91-usart.c index a694d702e574..f3583bdd475b 100644 --- a/drivers/spi/spi-at91-usart.c +++ b/drivers/spi/spi-at91-usart.c @@ -8,9 +8,12 @@ #include #include +#include +#include #include #include #include +#include #include #include #include @@ -59,6 +62,8 @@ #define US_INIT \ (US_MR_SPI_MASTER | US_MR_CHRL | US_MR_CLKO | US_MR_WRDBT) +#define US_DMA_MIN_BYTES 16 +#define US_DMA_TIMEOUT (msecs_to_jiffies(1000)) /* Register access macros */ #define at91_usart_spi_readl(port, reg) \ @@ -72,14 +77,19 @@ writeb_relaxed((value), (port)->regs + US_##reg) struct at91_usart_spi { + struct platform_device *mpdev; struct spi_transfer *current_transfer; void __iomem*regs; struct device *dev; struct clk *clk; + struct completion xfer_completion; + /*used in interrupt to protect data reading*/ spinlock_t lock; + phys_addr_t phybase; + int irq; unsigned intcurrent_tx_remaining_bytes; unsigned intcurrent_rx_remaining_bytes; @@ -88,8 +98,182 @@ struct at91_usart_spi { u32 status; boolxfer_failed; + booluse_dma; }; +static void dma_callback(void *data) +{ + struct spi_controller *ctlr = data; + struct at91_usart_spi *aus = spi_master_get_devdata(ctlr); + + at91_usart_spi_writel(aus, IER, US_IR_RXRDY); + aus->current_rx_remaining_bytes = 0; + complete(&aus->xfer_completion); +} + +static bool at91_usart_spi_can_dma(struct spi_controller *ctrl, + struct spi_device *spi, + struct spi_transfer *xfer) +{ + struct at91_usart_spi *aus = spi_master_get_devdata(ctrl); + + return aus->use_dma && xfer->len >= US_DMA_MIN_BYTES; +} + +static int at91_usart_spi_configure_dma(struct spi_controller *ctlr, + struct at91_usart_spi *aus) +{ + struct dma_slave_config slave_config; + struct device *dev = &aus->mpdev->dev; + phys_addr_t phybase = aus->phybase; + dma_cap_mask_t mask; + int err = 0; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + ctlr->dma_tx = dma_request_slave_channel_reason(dev, "tx"); + if (IS_ERR_OR_NULL(ctlr->dma_tx)) { + if (IS_ERR(ctlr->dma_tx)) { + err = PTR_ERR(ctlr->dma_tx); + goto at91_usart_spi_error_clear; + } + + dev_dbg(dev, + "DMA TX channel not available, SPI unable to use DMA\n"); + err = -EBUSY; + goto at91_usart_spi_error_clear; + } + + ctlr->dma_rx = dma_request_slave_channel_reason(dev, "rx"); + if (IS_ERR_OR_NULL(ctlr->dma_rx)) { + if (IS_ERR(ctlr->dma_rx)) { + err = PTR_ERR(ctlr->dma_rx); + goto at91_usart_spi_error; + } + + dev_dbg(dev, + "DMA RX channel not available, SPI unable to use DMA\n"); + err = -EBUSY; + goto at91_usart_spi_error; + } + + slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + slave_config.dst_addr = (dma_addr_t)phybase + US_THR; + slave_config.src_addr = (dma_addr_t)phybase + US_RHR; + slave_config.src_maxburst = 1; + slave_config.dst_maxburst = 1; + slave_config.device_fc = false; + + slave_config.direction = DMA_DEV_TO_MEM; + if (dmaengine_slave_config(ctlr->dma_rx, &slave_config)) { + dev_err(&ctlr->dev, + "failed to configure rx dma channel\n"); + err = -EINVAL; + goto at91_usart_spi_error; + } + + slave_config.direction = DMA_MEM_TO_DEV; + if (dmaengine_slave_config(ctlr->dma_tx, &slave_config)) { + dev_err(&ctlr->dev, + "failed to configure tx dma channel\n"); + err = -EINVAL; + goto at91_usart_spi_error; + } + + aus->use_d
[PATCH v2 1/2] dt-bindings: mfd: atmel-usart: add DMA bindings for USART in SPI mode
The bindings for DMA are now common for both drivers of the USART IP. The node given as an example for USART in SPI mode has been updated in order to include DMA bindings. Signed-off-by: Radu Pirea --- .../devicetree/bindings/mfd/atmel-usart.txt | 20 ++- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/atmel-usart.txt b/Documentation/devicetree/bindings/mfd/atmel-usart.txt index 7f0cd72f47d2..699fd3c9ace8 100644 --- a/Documentation/devicetree/bindings/mfd/atmel-usart.txt +++ b/Documentation/devicetree/bindings/mfd/atmel-usart.txt @@ -17,17 +17,24 @@ Required properties for USART in SPI mode: - cs-gpios: chipselects (internal cs not supported) - atmel,usart-mode : Must be (found in dt-bindings/mfd/at91-usart.h) +Optional properties in serial and SPI mode: +- dma bindings for dma transfer: + - dmas: DMA specifier, consisting of a phandle to DMA controller node, + memory peripheral interface and USART DMA channel ID, FIFO configuration. + The order of DMA channels is fixed. The first DMA channel must be TX + associated channel and the second one must be RX associated channel. + Refer to dma.txt and atmel-dma.txt for details. + - dma-names: "tx" for TX channel. +"rx" for RX channel. +The order of dma-names is also fixed. The first name must be "tx" +and the second one must be "rx" as in the examples below. + Optional properties in serial mode: - atmel,use-dma-rx: use of PDC or DMA for receiving data - atmel,use-dma-tx: use of PDC or DMA for transmitting data - {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD line respectively. It will use specified PIO instead of the peripheral function pin for the USART feature. If unsure, don't specify this property. -- add dma bindings for dma transfer: - - dmas: DMA specifier, consisting of a phandle to DMA controller node, - memory peripheral interface and USART DMA channel ID, FIFO configuration. - Refer to dma.txt and atmel-dma.txt for details. - - dma-names: "rx" for RX channel, "tx" for TX channel. - atmel,fifo-size: maximum number of data the RX and TX FIFOs can store for FIFO capable USARTs. - rs485-rts-delay, rs485-rx-during-tx, linux,rs485-enabled-at-boot-time: see rs485.txt @@ -81,5 +88,8 @@ Example: interrupts = <12 IRQ_TYPE_LEVEL_HIGH 5>; clocks = <&usart0_clk>; clock-names = "usart"; + dmas = <&dma0 2 AT91_DMA_CFG_PER_ID(3)>, + <&dma0 2 (AT91_DMA_CFG_PER_ID(4) | AT91_DMA_CFG_FIFOCFG_ASAP)>; + dma-names = "tx", "rx"; cs-gpios = <&pioB 3 0>; }; -- 2.21.0
[PATCH v2 0/2] DMA support for AT91 USART in SPI mode
Hi, This is the version two of the patches with DMA support for spi-at91-usart driver. Changes in v2: - specified in bindings order of dmas and dma-names - changed DMA_FROM_DEVICE to DMA_DEV_TO_MEM and DMA_TO_DEVICE to DMA_MEM_TO_DEV when dmaengine_prep_slave_sg is called Changes in v1: - added DMA support Radu Pirea (2): dt-bindings: mfd: atmel-usart: add DMA bindings for USART in SPI mode spi: at91-usart: add DMA support .../devicetree/bindings/mfd/atmel-usart.txt | 20 +- drivers/spi/spi-at91-usart.c | 221 +- 2 files changed, 234 insertions(+), 7 deletions(-) -- 2.21.0
Re: [PATCH v12 0/6] Driver for at91 usart in spi mode
On Wed, 2018-09-12 at 14:12 +0100, Lee Jones wrote: > On Wed, 12 Sep 2018, Alexandre Belloni wrote: > > > On 12/09/2018 12:43:52+0100, Lee Jones wrote: > > > > > But ... we can't have it both ways. *Either* it's a true > > > > > MFD, in > > > > > which case it can/should have 2 separate compatible strings > > > > > which can > > > > > be specified directly from the DT. *Or* it's not an MFD. In > > > > > the > > > > > latter case, which I think we're all agreeing on (else we'd > > > > > have 2 > > > > > compatible strings), MFD is not the place to handle this (my > > > > > original > > > > > point). > > > > > > > > > > > > > If that is what bothers you, then let's move it out of mfd. > > > > > > As I've already mentioned. I don't just want it moved out of MFD > > > and > > > shoved somewhere else. My aim is to fix this properly. > > > > > > > If it is out of MFD, then I'm not sure why you would care too much > > about > > it as you won't be maintaining that code. And I still this what was > > done > > was correct but I'm open to test what you suggest. > > I care for the kernel in general, not just the areas I'm responsible > for. I guess I'm just that kinda guy! ;) Well, Lee, like you, I think this driver should not be a MFD driver, but Alex has a good point of view. > > > > > > So ... this is a USART device which can do SPI, right? > > > > > > > > > > My current thinking is that; as this is a USART device first > > > > > & > > > > > foremost, the USART should be probed in the first instance > > > > > regardless, > > > > > then if SPI mode is specified it (the USART driver) registers > > > > > the SPI > > > > > platform driver (as MFD does currently) and exits gracefully, > > > > > allowing > > > > > the SPI driver to take over. > > > > > > > > > > Spanner in the works: is it physically possible to change the > > > > > mode at > > > > > run-time? :s > > > > > > > > Yes it is possible but on Linux that will not happen without > > > > probing > > > > the drivers again. > > > > > > Not sure I understand what you mean. > > > > I was just commenting on changing the mode at runtime. > > Oh I see. My question was relating to whether the H/W is physically > capable of changing modes on-the-fly, rather than how Linux would > handle that. If this is something we'd wish to support, then it > would > have to be a single driver, which is why I was asking. By separating > the drivers this way, we are blocking that as a > possibility. Although > I guess the OP has already thought about that and made the decision > not to support it. Is possible to change modes on-the-fly, but you have no reason to do that. On the PCB you will have a SPI slave or a serial console :) Anyway, the current form of the driver, and through this I want to say "this ugly hack", allows the user to switch from serial to SPI mode by adding only one property to the device tree node of USART. If the driver were in his first form, a simple SPI driver, how you will make a dtsi file for an IP like this? You will add two nodes for the same IP in dtsi and will take care to enable correct node in dts? I think this driver is only a tradeoff between having an ugly hack in kernel or having an messy device tree. > > > > I'm suggesting that you use the same platform_* interfaces MFD > > > uses to > > > register the SPI driver if SPI mode has been selected. Only do > > > so > > > from the appropriate driver i.e. USART. > > > > Yeah, I understood that but I didn't comment because I'm not sure > > this > > will work yet. > > Other drivers already do this. Can you give me an example please? I am open to suggestions. Sorry for that acked-by. There was a lot of "reviewed-by", "acked-by", etc in a single version and I messed up :).
[PATCH v12 5/6] spi: at91-usart: add driver for at91-usart as spi
From: Radu Pirea 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 --- 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 diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index ad5d68e1dab7..6d9e309fab67 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 cb1f4378b87c..901ff606e6e5 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 ..a924657642fa --- /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_BRGR0x20 +#define US_VERSION 0xFC + +#define US_CR_RSTRXBIT(2) +#define US_CR_RSTTXBIT(3) +#define US_CR_RXEN BIT(4) +#define US_CR_RXDISBIT(5) +#define US_CR_TXEN BIT(6) +#define US_CR_TXDISBIT(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_WRDBTBIT(20) +#define US_MR_LOOP BIT(15) + +#define US_IR_RXRDYBIT(0) +#define US_IR_TXRDYBIT(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 intcurrent_tx_remaining_bytes; + unsigned intcurrent_rx_remaining_bytes; + + u32 spi_clk; + u32 status; + + boolxfer_failed; +}; + +static inline u32 at91_usart_spi_tx_ready(struct at91_usart_spi *aus) +{ + return aus->status &am
[PATCH v12 3/6] mfd: at91-usart: added mfd driver for usart
From: Radu Pirea 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-for-MFD-by: Lee Jones Acked-by: Nicolas Ferre --- 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 diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b860eb5aa194..a886672b960d 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 e9fd20dba18d..c7e66928abb9 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -184,6 +184,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 ..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"); -- 2.18.0
[PATCH v12 4/6] MAINTAINERS: add at91 usart spi driver
From: Radu Pirea Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea Acked-by: Nicolas Ferre --- MAINTAINERS | 7 +++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 8aeaa2cc3e14..1bb477aab33b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9363,6 +9363,13 @@ F: drivers/mfd/at91-usart.c F: include/dt-bindings/mfd/at91-usart.h F: Documentation/devicetree/bindings/mfd/atmel-usart.txt +MICROCHIP AT91 USART SPI DRIVER +M: Radu Pirea +L: linux-...@vger.kernel.org +S: Supported +F: drivers/spi/spi-at91-usart.c +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.18.0
[PATCH v12 1/6] MAINTAINERS: add at91 usart mfd driver
From: Radu Pirea Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea Acked-by: Nicolas Ferre Acked-for-MFD-by: Lee Jones --- MAINTAINERS | 9 + 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 544cac829cf4..8aeaa2cc3e14 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9322,6 +9322,7 @@ M:Richard Genoud S: Maintained F: drivers/tty/serial/atmel_serial.c F: drivers/tty/serial/atmel_serial.h +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt MICROCHIP / ATMEL DMA DRIVER M: Ludovic Desroches @@ -9354,6 +9355,14 @@ S: Supported F: drivers/mtd/nand/raw/atmel/* F: Documentation/devicetree/bindings/mtd/atmel-nand.txt +MICROCHIP AT91 USART MFD DRIVER +M: Radu Pirea +L: linux-kernel@vger.kernel.org +S: Supported +F: drivers/mfd/at91-usart.c +F: include/dt-bindings/mfd/at91-usart.h +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.18.0
[PATCH v12 6/6] tty/serial: atmel: change the driver to work under at91-usart mfd
From: Radu Pirea 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 --- drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 42 --- 2 files changed, 28 insertions(+), 15 deletions(-) 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", @@ -,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-&g
[PATCH v12 0/6] Driver for at91 usart in spi mode
Hi, Well, this is the 12th version of this patch series. In this version I fixed a warning from kbuild-robot and I have no idea how I forgot to add static in declaration of that functions. Also I fixed the example for the SPI driver in bindings. Currently I am not working for Microchip, but I will continue to maintain and improve this driver. So yes, this is the reason that I changed my email address from MAINTAINERS file. Changes in v12: - fixed interrupts property in example from bindings of SPI driver - changed email address in MAINTAINERS - added static to declaration of few functions in SPI driver(kbuild-robot warning) Changes in v11: - removed "depends on HAS_DMA" from drivers/spi/Kconfig because the driver has no dma support - changed "selects MFD_AT91_USART" to "depends on MFD_AT91_USART" in drivers/spi/Kconfig - changed comment style in spi-at91-usart.c Changes in v10: -fixed kbuild test robot warning Changes in v9: - minor changes - rebased on top of broonie/for-4.19 Changes in v8: - fixed passing an empty mfd cell if "atmel,usart-mode" value is invalid Changes in v7: - synced up SPDIX license with module license - numbering of usart modes starts from 0 insteand of 1 Changes in v6: - removed unused compatible strings from serial and spi drivers Changes in v5: - fixed usage of stdout-path property with atmel_serial driver Changes in v4: - modified the spi driver to use cs gpio support form spi subsystem - fixed dma transfers for serial driver - squashed binding for spi and serial and moved them to mfd/atmel-usart.txt Changes in v3: - fixed spi slaves probing Changes in v2: - added at91-usart mfd driver - modified spi-at91-usart driver to work as mfd driver child - modified atmel_serial driver to work as mfd driver child Changes in v1: - added spi-at91-usart driver Radu Pirea (6): MAINTAINERS: add at91 usart mfd driver dt-bindings: add binding for atmel-usart in SPI mode mfd: at91-usart: added mfd driver for usart MAINTAINERS: add at91 usart spi driver spi: at91-usart: add driver for at91-usart as spi tty/serial: atmel: change the driver to work under at91-usart mfd .../bindings/{serial => mfd}/atmel-usart.txt | 25 +- MAINTAINERS | 16 + drivers/mfd/Kconfig | 9 + drivers/mfd/Makefile | 1 + drivers/mfd/at91-usart.c | 71 +++ drivers/spi/Kconfig | 8 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 432 ++ drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 42 +- include/dt-bindings/mfd/at91-usart.h | 17 + 11 files changed, 606 insertions(+), 17 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) create mode 100644 drivers/mfd/at91-usart.c create mode 100644 drivers/spi/spi-at91-usart.c create mode 100644 include/dt-bindings/mfd/at91-usart.h -- 2.18.0
[PATCH v12 2/6] dt-bindings: add binding for atmel-usart in SPI mode
From: Radu Pirea This patch moves the bindings for serial from serial/atmel-usart.txt to mfd/atmel-usart.txt and adds bindings for USART in SPI mode. Signed-off-by: Radu Pirea Reviewed-by: Rob Herring Acked-for-MFD-by: Lee Jones Acked-by: Nicolas Ferre --- .../bindings/{serial => mfd}/atmel-usart.txt | 25 +-- include/dt-bindings/mfd/at91-usart.h | 17 + 2 files changed, 40 insertions(+), 2 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) create mode 100644 include/dt-bindings/mfd/at91-usart.h diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/mfd/atmel-usart.txt similarity index 76% rename from Documentation/devicetree/bindings/serial/atmel-usart.txt rename to Documentation/devicetree/bindings/mfd/atmel-usart.txt index 7c0d6b2f53e4..7f0cd72f47d2 100644 --- a/Documentation/devicetree/bindings/serial/atmel-usart.txt +++ b/Documentation/devicetree/bindings/mfd/atmel-usart.txt @@ -1,6 +1,6 @@ * Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART) -Required properties: +Required properties for USART: - compatible: Should be "atmel,-usart" or "atmel,-dbgu" The compatible indicated will be the first SoC to support an additional mode or an USART new feature. @@ -11,7 +11,13 @@ Required properties: Required elements: "usart" - clocks: phandles to input clocks. -Optional properties: +Required properties for USART in SPI mode: +- #size-cells : Must be <0> +- #address-cells : Must be <1> +- cs-gpios: chipselects (internal cs not supported) +- atmel,usart-mode : Must be (found in dt-bindings/mfd/at91-usart.h) + +Optional properties in serial mode: - atmel,use-dma-rx: use of PDC or DMA for receiving data - atmel,use-dma-tx: use of PDC or DMA for transmitting data - {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD line respectively. @@ -62,3 +68,18 @@ Example: dma-names = "tx", "rx"; atmel,fifo-size = <32>; }; + +- SPI mode: + #include + + spi0: spi@f001c000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "atmel,at91rm9200-usart", "atmel,at91sam9260-usart"; + atmel,usart-mode = ; + reg = <0xf001c000 0x100>; + interrupts = <12 IRQ_TYPE_LEVEL_HIGH 5>; + clocks = <&usart0_clk>; + clock-names = "usart"; + cs-gpios = <&pioB 3 0>; + }; diff --git a/include/dt-bindings/mfd/at91-usart.h b/include/dt-bindings/mfd/at91-usart.h new file mode 100644 index ..2de5bc312e1e --- /dev/null +++ b/include/dt-bindings/mfd/at91-usart.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * This header provides macros for AT91 USART DT bindings. + * + * Copyright (C) 2018 Microchip Technology + * + * Author: Radu Pirea + * + */ + +#ifndef __DT_BINDINGS_AT91_USART_H__ +#define __DT_BINDINGS_AT91_USART_H__ + +#define AT91_USART_MODE_SERIAL 0 +#define AT91_USART_MODE_SPI1 + +#endif /* __DT_BINDINGS_AT91_USART_H__ */ -- 2.18.0
[RESEND PATCH v11 0/6] Driver for at91 usart in spi mode
Hello, This is the 11th version of driver. I added a mfd driver which by default probes atmel_serial driver and if in dt is specified to probe the spi driver, then the spi-at91-usart driver will be probed. The compatible for atmel_serial is now the compatible for at91-usart mfd driver and compatilbe for atmel_serial driver was changed in order to keep the bindings for serial as they are. @Lee, could you take this patch series into your tree? I addressed all Mark remarks. In this resend I changed my email address from MAINTAINERS file. Changes in v11: - removed "depends on HAS_DMA" from drivers/spi/Kconfig because the driver has no dma support - changed "selects MFD_AT91_USART" to "depends on MFD_AT91_USART" in drivers/spi/Kconfig - changed comment style in spi-at91-usart.c Changes in v10: -fixed kbuild test robot warning Changes in v9: - minor changes - rebased on top of broonie/for-4.19 Changes in v8: - fixed passing an empty mfd cell if "atmel,usart-mode" value is invalid Changes in v7: - synced up SPDIX license with module license - numbering of usart modes starts from 0 insteand of 1 Changes in v6: - removed unused compatible strings from serial and spi drivers Changes in v5: - fixed usage of stdout-path property with atmel_serial driver Changes in v4: - modified the spi driver to use cs gpio support form spi subsystem - fixed dma transfers for serial driver - squashed binding for spi and serial and moved them to mfd/atmel-usart.txt Changes in v3: - fixed spi slaves probing Changes in v2: - added at91-usart mfd driver - modified spi-at91-usart driver to work as mfd driver child - modified atmel_serial driver to work as mfd driver child Changes in v1: - added spi-at91-usart driver Radu Pirea (6): MAINTAINERS: add at91 usart mfd driver dt-bindings: add binding for atmel-usart in SPI mode mfd: at91-usart: added mfd driver for usart MAINTAINERS: add at91 usart spi driver spi: at91-usart: add driver for at91-usart as spi tty/serial: atmel: change the driver to work under at91-usart mfd .../bindings/{serial => mfd}/atmel-usart.txt | 25 +- MAINTAINERS | 16 + drivers/mfd/Kconfig | 9 + drivers/mfd/Makefile | 1 + drivers/mfd/at91-usart.c | 71 +++ drivers/spi/Kconfig | 8 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 432 ++ drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 42 +- include/dt-bindings/mfd/at91-usart.h | 17 + 11 files changed, 606 insertions(+), 17 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) create mode 100644 drivers/mfd/at91-usart.c create mode 100644 drivers/spi/spi-at91-usart.c create mode 100644 include/dt-bindings/mfd/at91-usart.h -- 2.18.0
[RESEND PATCH v11 2/6] dt-bindings: add binding for atmel-usart in SPI mode
This patch moves the bindings for serial from serial/atmel-usart.txt to mfd/atmel-usart.txt and adds bindings for USART in SPI mode. Signed-off-by: Radu Pirea Reviewed-by: Rob Herring Acked-for-MFD-by: Lee Jones Acked-by: Nicolas Ferre --- .../bindings/{serial => mfd}/atmel-usart.txt | 25 +-- include/dt-bindings/mfd/at91-usart.h | 17 + 2 files changed, 40 insertions(+), 2 deletions(-) rename Documentation/devicetree/bindings/{serial => mfd}/atmel-usart.txt (76%) create mode 100644 include/dt-bindings/mfd/at91-usart.h diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/mfd/atmel-usart.txt similarity index 76% rename from Documentation/devicetree/bindings/serial/atmel-usart.txt rename to Documentation/devicetree/bindings/mfd/atmel-usart.txt index 7c0d6b2f53e4..0348fef0f497 100644 --- a/Documentation/devicetree/bindings/serial/atmel-usart.txt +++ b/Documentation/devicetree/bindings/mfd/atmel-usart.txt @@ -1,6 +1,6 @@ * Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART) -Required properties: +Required properties for USART: - compatible: Should be "atmel,-usart" or "atmel,-dbgu" The compatible indicated will be the first SoC to support an additional mode or an USART new feature. @@ -11,7 +11,13 @@ Required properties: Required elements: "usart" - clocks: phandles to input clocks. -Optional properties: +Required properties for USART in SPI mode: +- #size-cells : Must be <0> +- #address-cells : Must be <1> +- cs-gpios: chipselects (internal cs not supported) +- atmel,usart-mode : Must be (found in dt-bindings/mfd/at91-usart.h) + +Optional properties in serial mode: - atmel,use-dma-rx: use of PDC or DMA for receiving data - atmel,use-dma-tx: use of PDC or DMA for transmitting data - {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD line respectively. @@ -62,3 +68,18 @@ Example: dma-names = "tx", "rx"; atmel,fifo-size = <32>; }; + +- SPI mode: + #include + + spi0: spi@f001c000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "atmel,at91rm9200-usart", "atmel,at91sam9260-usart"; + atmel,usart-mode = ; + reg = <0xf001c000 0x100>; + interrupts = <12 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&usart0_clk>; + clock-names = "usart"; + cs-gpios = <&pioB 3 0>; + }; diff --git a/include/dt-bindings/mfd/at91-usart.h b/include/dt-bindings/mfd/at91-usart.h new file mode 100644 index ..2de5bc312e1e --- /dev/null +++ b/include/dt-bindings/mfd/at91-usart.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * This header provides macros for AT91 USART DT bindings. + * + * Copyright (C) 2018 Microchip Technology + * + * Author: Radu Pirea + * + */ + +#ifndef __DT_BINDINGS_AT91_USART_H__ +#define __DT_BINDINGS_AT91_USART_H__ + +#define AT91_USART_MODE_SERIAL 0 +#define AT91_USART_MODE_SPI1 + +#endif /* __DT_BINDINGS_AT91_USART_H__ */ -- 2.18.0
[RESEND PATCH v11 4/6] MAINTAINERS: add at91 usart spi driver
Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea Acked-by: Nicolas Ferre --- MAINTAINERS | 7 +++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 94b37382cd2b..d58bc2d6bb3d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9542,6 +9542,13 @@ F: drivers/mfd/at91-usart.c F: include/dt-bindings/mfd/at91-usart.h F: Documentation/devicetree/bindings/mfd/atmel-usart.txt +MICROCHIP AT91 USART SPI DRIVER +M: Radu Pirea +L: linux-...@vger.kernel.org +S: Supported +F: drivers/spi/spi-at91-usart.c +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.18.0
[RESEND PATCH v11 5/6] 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 --- 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 diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 7580eb76ab18..181b5f2e831d 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 1920b6cc2b7e..7385bbd37dcf 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 ..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_BRGR0x20 +#define US_VERSION 0xFC + +#define US_CR_RSTRXBIT(2) +#define US_CR_RSTTXBIT(3) +#define US_CR_RXEN BIT(4) +#define US_CR_RXDISBIT(5) +#define US_CR_TXEN BIT(6) +#define US_CR_TXDISBIT(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_WRDBTBIT(20) +#define US_MR_LOOP BIT(15) + +#define US_IR_RXRDYBIT(0) +#define US_IR_TXRDYBIT(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 intcurrent_tx_remaining_bytes; + unsigned intcurrent_rx_remaining_bytes; + + u32 spi_clk; + u32 status; + + boolxfer_failed; +}; + +static inline u32 at91_usart_spi_tx_ready(struct at91_usart_spi *aus) +{ + return aus->status & US_IR_TXRDY; +} + +st
[RESEND PATCH v11 1/6] MAINTAINERS: add at91 usart mfd driver
Added entry for at91 usart mfd driver. Signed-off-by: Radu Pirea Acked-by: Nicolas Ferre Acked-for-MFD-by: Lee Jones --- MAINTAINERS | 9 + 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index a5b256b25905..94b37382cd2b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9502,6 +9502,7 @@ M:Richard Genoud S: Maintained F: drivers/tty/serial/atmel_serial.c F: drivers/tty/serial/atmel_serial.h +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt MICROCHIP / ATMEL DMA DRIVER M: Ludovic Desroches @@ -9533,6 +9534,14 @@ S: Supported F: drivers/mtd/nand/raw/atmel/* F: Documentation/devicetree/bindings/mtd/atmel-nand.txt +MICROCHIP AT91 USART MFD DRIVER +M: Radu Pirea +L: linux-kernel@vger.kernel.org +S: Supported +F: drivers/mfd/at91-usart.c +F: include/dt-bindings/mfd/at91-usart.h +F: Documentation/devicetree/bindings/mfd/atmel-usart.txt + MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER M: Woojung Huh M: Microchip Linux Driver Support -- 2.18.0
[RESEND PATCH v11 6/6] 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 --- drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 42 --- 2 files changed, 28 insertions(+), 15 deletions(-) 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", @@ -,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
[RESEND PATCH v11 3/6] mfd: at91-usart: added 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-for-MFD-by: Lee Jones Acked-by: Nicolas Ferre --- 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 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 ..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"); -- 2.18.0
[PATCH v2 0/6] Driver for at91 usart in spi mode
Hello, This is the second version of driver. I added a mfd driver which by default probes atmel_serial driver and if in dt is specified to probe the spi driver, then the spi-at91-usart driver will be probed. The compatible for atmel_serial is now the compatible for at91-usart mfd driver and compatilbe for atmel_serial driver was changed in order to keep the bindings for serial as they are. Changes in v1: - added spi-at91-usart driver Changes in v2: - added at91-usart mfd driver - modified spi-at91-usart driver to work as mfd driver child - modified atmel_serial driver to work as mfd driver child Radu Pirea (6): MAINTAINERS: add at91 usart mfd driver mfd: at91-usart: added mfd driver for usart MAINTAINERS: add at91 usart spi driver dt-bindings: add binding for at91-usart in spi mode spi: at91-usart: add driver for at91-usart as spi tty/serial: atmel: changed the driver to work under at91-usart mfd .../bindings/spi/microchip,at91-usart-spi.txt | 28 + MAINTAINERS | 14 + drivers/mfd/Kconfig | 10 + drivers/mfd/Makefile | 1 + drivers/mfd/at91-usart.c | 81 +++ drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/spi-at91-usart.c | 545 ++ drivers/tty/serial/Kconfig| 1 + drivers/tty/serial/atmel_serial.c | 29 +- include/dt-bindings/mfd/at91-usart.h | 17 + 11 files changed, 722 insertions(+), 14 deletions(-) create mode 100644 Documentation/devicetree/bindings/spi/microchip,at91-usart-spi.txt create mode 100644 drivers/mfd/at91-usart.c create mode 100644 drivers/spi/spi-at91-usart.c create mode 100644 include/dt-bindings/mfd/at91-usart.h -- 2.17.0