Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1291644 > unrolled thread

[PATCH v2 00/14] Initial Microchip PIC32MZDA Support

Started byJoshua Henderson <joshua.henderson@microchip.com>
First post2015-12-14 23:40 +0100
Last post2015-12-14 23:50 +0100
Articles 18 — 6 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v2 00/14] Initial Microchip PIC32MZDA Support Joshua Henderson <joshua.henderson@microchip.com> - 2015-12-14 23:40 +0100
    [PATCH v2 03/14] DEVICETREE: Add PIC32 clock binding documentation Joshua Henderson <joshua.henderson@microchip.com> - 2015-12-14 23:40 +0100
      Re: [PATCH v2 03/14] DEVICETREE: Add PIC32 clock binding  documentation Rob Herring <robh@kernel.org> - 2015-12-18 16:50 +0100
        Re: [PATCH v2 03/14] DEVICETREE: Add PIC32 clock binding  documentation Purna Chandra Mandal <purna.mandal@microchip.com> - 2015-12-19 13:00 +0100
    [PATCH v2 01/14] DEVICETREE: Add bindings for PIC32 interrupt controller Joshua Henderson <joshua.henderson@microchip.com> - 2015-12-14 23:50 +0100
      Re: [PATCH v2 01/14] DEVICETREE: Add bindings for PIC32 interrupt  controller Rob Herring <robh@kernel.org> - 2015-12-15 00:40 +0100
    [PATCH v2 13/14] MIPS: dts: Add initial DTS for the PIC32MZDA Starter Kit Joshua Henderson <joshua.henderson@microchip.com> - 2015-12-14 23:50 +0100
    [PATCH v2 09/14] DEVICETREE: Add bindings for PIC32 UART driver Joshua Henderson <joshua.henderson@microchip.com> - 2015-12-14 23:50 +0100
      Re: [PATCH v2 09/14] DEVICETREE: Add bindings for PIC32 UART driver Rob Herring <robh@kernel.org> - 2015-12-15 21:10 +0100
    [PATCH v2 11/14] DEVICETREE: Add bindings for PIC32 SDHCI host controller Joshua Henderson <joshua.henderson@microchip.com> - 2015-12-14 23:50 +0100
      Re: [PATCH v2 11/14] DEVICETREE: Add bindings for PIC32 SDHCI host  controller Rob Herring <robh@kernel.org> - 2015-12-15 21:10 +0100
    [PATCH v2 12/14] mmc: sdhci-pic32: Add PIC32 SDHCI host controller driver Joshua Henderson <joshua.henderson@microchip.com> - 2015-12-14 23:50 +0100
      Re: [PATCH v2 12/14] mmc: sdhci-pic32: Add PIC32 SDHCI host  controller driver Andy Green <andy.green@linaro.org> - 2015-12-15 01:40 +0100
        RE: [PATCH v2 12/14] mmc: sdhci-pic32: Add PIC32 SDHCI host  controller driver <Paul.Thacker@microchip.com> - 2015-12-16 18:40 +0100
      Re: [PATCH v2 12/14] mmc: sdhci-pic32: Add PIC32 SDHCI host  controller driver Ulf Hansson <ulf.hansson@linaro.org> - 2015-12-16 11:50 +0100
        RE: [PATCH v2 12/14] mmc: sdhci-pic32: Add PIC32 SDHCI host  controller driver <Paul.Thacker@microchip.com> - 2015-12-17 19:10 +0100
    [PATCH v2 10/14] serial: pic32_uart: Add PIC32 UART driver Joshua Henderson <joshua.henderson@microchip.com> - 2015-12-14 23:50 +0100
    [PATCH v2 14/14] MIPS: pic32mzda: Add initial PIC32MZDA Starter Kit defconfig Joshua Henderson <joshua.henderson@microchip.com> - 2015-12-14 23:50 +0100

#1291644 — [PATCH v2 00/14] Initial Microchip PIC32MZDA Support

FromJoshua Henderson <joshua.henderson@microchip.com>
Date2015-12-14 23:40 +0100
Subject[PATCH v2 00/14] Initial Microchip PIC32MZDA Support
Message-ID<qFJWF-3Ss-7@gated-at.bofh.it>
This patch series adds support for the Microchip PIC32MZDA MIPS platform.
All drivers required to boot from a MMC uSD card are included. Clock,
external interrupt controller, serial, SDHCI, and pinctrl drivers are
included. This has been tested on a PIC32MZDA Starter Kit. A tree with
these changes is available at [0].

[0] https://github.com/joshua-henderson/linux/tree/pic32-upstream-v2

Changes since v1 (https://lkml.org/lkml/2015/11/20/848):

	+ Rename all DT compatible properties to be chip specific.
	+ Remove hardware interrupt priorities from interrupt controller DT
	  bindings.
	+ Remove all dependencies on include headers used by PIC32 DTS
	  files.
	+ Remove arch/mips/include/asm/mach-pic32/gpio.h
	+ Drop usage of the following, mostly non-standard, properties in
	  DT bindings:
		device_type
		piomode
		no-1-8-v
		uart-has-rtscts
		clock-frequency => assigned-clock-rate
	+ Remove PIC32 memory PLL support from DT.
	+ Replace empty 'ranges' with populated one for clock tree node.
	+ Rename all instances of "USART" to "UART".
	+ Remove 'interrupts' property from FSCM of PIC32 clock tree node.
	+ Add default REFCLK rate initialization required for SDHCI in DTS.
	+ Remove default frequency setup for REFOSC clocks in -clk DTS.
	+ Address missing static on local functions and other sparse
	  warnings in several drivers.
	+ Update pinctrl driver to address major binding and architectural
	  issues.
	+ Remove redundant probing 'pb7_clk' to find CPU clock.
	+ Remove unused PIC32 MPLL support.
	+ Remove support for initializing default parent/rate for REFOSC
	  clocks.
	+ Be consistent and use only "SDHCI" when refering to SD host
	  controller
	+ Remove unecessary PIC32 sdhci_ops min clock function.
	+ Make platform PIC32[_CLR|_SET|_INV] register macros safer.

Andrei Pistirica (4):
  DEVICETREE: Add bindings for PIC32 UART driver
  serial: pic32_uart: Add PIC32 UART driver
  DEVICETREE: Add bindings for PIC32 SDHCI host controller
  mmc: sdhci-pic32: Add PIC32 SDHCI host controller driver

Cristian Birsan (2):
  DEVICETREE: Add bindings for PIC32 interrupt controller
  irqchip: irq-pic32-evic: Add support for PIC32 interrupt controller

Joshua Henderson (6):
  DEVICETREE: Add bindings for PIC32/MZDA platforms
  MIPS: Add support for PIC32MZDA platform
  DEVICETREE: Add bindings for PIC32 pin control and GPIO
  pinctrl: pinctrl-pic32: Add PIC32 pin control driver
  MIPS: dts: Add initial DTS for the PIC32MZDA Starter Kit
  MIPS: pic32mzda: Add initial PIC32MZDA Starter Kit defconfig

Purna Chandra Mandal (2):
  DEVICETREE: Add PIC32 clock binding documentation
  clk: clk-pic32: Add PIC32 clock driver

 .../devicetree/bindings/clock/microchip,pic32.txt  |  256 +++
 .../bindings/gpio/microchip,pic32-gpio.txt         |   32 +
 .../interrupt-controller/microchip,pic32-evic.txt  |   58 +
 .../bindings/mips/pic32/microchip,pic32mzda.txt    |   33 +
 .../bindings/mmc/microchip,sdhci-pic32.txt         |   29 +
 .../bindings/pinctrl/microchip,pic32-pinctrl.txt   |   93 +
 .../bindings/serial/microchip,pic32-uart.txt       |   29 +
 arch/mips/Kbuild.platforms                         |    1 +
 arch/mips/Kconfig                                  |    9 +
 arch/mips/boot/dts/Makefile                        |    1 +
 arch/mips/boot/dts/pic32/Makefile                  |   12 +
 arch/mips/boot/dts/pic32/pic32mzda-clk.dtsi        |  235 ++
 arch/mips/boot/dts/pic32/pic32mzda.dtsi            |  275 +++
 arch/mips/boot/dts/pic32/pic32mzda_sk.dts          |  151 ++
 arch/mips/configs/pic32mzda_defconfig              |   88 +
 .../include/asm/mach-pic32/cpu-feature-overrides.h |   32 +
 arch/mips/include/asm/mach-pic32/irq.h             |   22 +
 arch/mips/include/asm/mach-pic32/pic32.h           |   44 +
 arch/mips/include/asm/mach-pic32/spaces.h          |   24 +
 arch/mips/pic32/Kconfig                            |   50 +
 arch/mips/pic32/Makefile                           |    6 +
 arch/mips/pic32/Platform                           |    7 +
 arch/mips/pic32/common/Makefile                    |    5 +
 arch/mips/pic32/common/irq.c                       |   21 +
 arch/mips/pic32/common/reset.c                     |   62 +
 arch/mips/pic32/pic32mzda/Makefile                 |    9 +
 arch/mips/pic32/pic32mzda/config.c                 |  126 ++
 arch/mips/pic32/pic32mzda/early_clk.c              |  106 +
 arch/mips/pic32/pic32mzda/early_console.c          |  171 ++
 arch/mips/pic32/pic32mzda/early_pin.c              |  275 +++
 arch/mips/pic32/pic32mzda/early_pin.h              |  241 ++
 arch/mips/pic32/pic32mzda/init.c                   |  156 ++
 arch/mips/pic32/pic32mzda/pic32mzda.h              |   29 +
 arch/mips/pic32/pic32mzda/time.c                   |   44 +
 drivers/clk/Kconfig                                |    3 +
 drivers/clk/Makefile                               |    1 +
 drivers/clk/clk-pic32.c                            | 1804 +++++++++++++++
 drivers/irqchip/Makefile                           |    1 +
 drivers/irqchip/irq-pic32-evic.c                   |  321 +++
 drivers/mmc/host/Kconfig                           |   11 +
 drivers/mmc/host/Makefile                          |    1 +
 drivers/mmc/host/sdhci-pic32.c                     |  291 +++
 drivers/pinctrl/Kconfig                            |   17 +
 drivers/pinctrl/Makefile                           |    1 +
 drivers/pinctrl/pinctrl-pic32.c                    | 2339 ++++++++++++++++++++
 drivers/pinctrl/pinctrl-pic32.h                    |  141 ++
 drivers/tty/serial/Kconfig                         |   21 +
 drivers/tty/serial/Makefile                        |    1 +
 drivers/tty/serial/pic32_uart.c                    |  927 ++++++++
 drivers/tty/serial/pic32_uart.h                    |  198 ++
 include/linux/irqchip/pic32-evic.h                 |   19 +
 include/linux/platform_data/sdhci-pic32.h          |   22 +
 include/uapi/linux/serial_core.h                   |    3 +
 53 files changed, 8854 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/microchip,pic32.txt
 create mode 100644 Documentation/devicetree/bindings/gpio/microchip,pic32-gpio.txt
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/microchip,pic32-evic.txt
 create mode 100644 Documentation/devicetree/bindings/mips/pic32/microchip,pic32mzda.txt
 create mode 100644 Documentation/devicetree/bindings/mmc/microchip,sdhci-pic32.txt
 create mode 100644 Documentation/devicetree/bindings/pinctrl/microchip,pic32-pinctrl.txt
 create mode 100644 Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt
 create mode 100644 arch/mips/boot/dts/pic32/Makefile
 create mode 100644 arch/mips/boot/dts/pic32/pic32mzda-clk.dtsi
 create mode 100644 arch/mips/boot/dts/pic32/pic32mzda.dtsi
 create mode 100644 arch/mips/boot/dts/pic32/pic32mzda_sk.dts
 create mode 100644 arch/mips/configs/pic32mzda_defconfig
 create mode 100644 arch/mips/include/asm/mach-pic32/cpu-feature-overrides.h
 create mode 100644 arch/mips/include/asm/mach-pic32/irq.h
 create mode 100644 arch/mips/include/asm/mach-pic32/pic32.h
 create mode 100644 arch/mips/include/asm/mach-pic32/spaces.h
 create mode 100644 arch/mips/pic32/Kconfig
 create mode 100644 arch/mips/pic32/Makefile
 create mode 100644 arch/mips/pic32/Platform
 create mode 100644 arch/mips/pic32/common/Makefile
 create mode 100644 arch/mips/pic32/common/irq.c
 create mode 100644 arch/mips/pic32/common/reset.c
 create mode 100644 arch/mips/pic32/pic32mzda/Makefile
 create mode 100644 arch/mips/pic32/pic32mzda/config.c
 create mode 100644 arch/mips/pic32/pic32mzda/early_clk.c
 create mode 100644 arch/mips/pic32/pic32mzda/early_console.c
 create mode 100644 arch/mips/pic32/pic32mzda/early_pin.c
 create mode 100644 arch/mips/pic32/pic32mzda/early_pin.h
 create mode 100644 arch/mips/pic32/pic32mzda/init.c
 create mode 100644 arch/mips/pic32/pic32mzda/pic32mzda.h
 create mode 100644 arch/mips/pic32/pic32mzda/time.c
 create mode 100644 drivers/clk/clk-pic32.c
 create mode 100644 drivers/irqchip/irq-pic32-evic.c
 create mode 100644 drivers/mmc/host/sdhci-pic32.c
 create mode 100644 drivers/pinctrl/pinctrl-pic32.c
 create mode 100644 drivers/pinctrl/pinctrl-pic32.h
 create mode 100644 drivers/tty/serial/pic32_uart.c
 create mode 100644 drivers/tty/serial/pic32_uart.h
 create mode 100644 include/linux/irqchip/pic32-evic.h
 create mode 100644 include/linux/platform_data/sdhci-pic32.h

--
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1291650 — [PATCH v2 03/14] DEVICETREE: Add PIC32 clock binding documentation

FromJoshua Henderson <joshua.henderson@microchip.com>
Date2015-12-14 23:40 +0100
Subject[PATCH v2 03/14] DEVICETREE: Add PIC32 clock binding documentation
Message-ID<qFJWI-3Ss-75@gated-at.bofh.it>
In reply to#1291644
From: Purna Chandra Mandal <purna.mandal@microchip.com>

Document the devicetree bindings for the clock driver found on Microchip
PIC32 class devices.

Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
Signed-off-by: Joshua Henderson <joshua.henderson@microchip.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
---
 .../devicetree/bindings/clock/microchip,pic32.txt  |  256 ++++++++++++++++++++
 1 file changed, 256 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/microchip,pic32.txt

diff --git a/Documentation/devicetree/bindings/clock/microchip,pic32.txt b/Documentation/devicetree/bindings/clock/microchip,pic32.txt
new file mode 100644
index 0000000..f50c653
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/microchip,pic32.txt
@@ -0,0 +1,256 @@
+Binding for a Clock hardware block found on
+certain Microchip PIC32 MCU devices.
+
+Microchip SoC clocks-node consists of few oscillators, PLL, multiplexer
+and few divider nodes.
+
+We will find only the base address of the clock tree, this base
+address is common for some of the subnodes, not all. If no address is
+specified for any of subnode base address of the clock tree will be
+treated as its base. Each of subnodes follow the same common clock
+binding with some additional optional properties.
+
+	clocks_node {
+		reg = <>;
+
+		spll_node {
+			...
+		};
+
+		frcdiv_node {
+			...
+		};
+
+		sysclk_mux_node {
+			...
+		};
+
+		pbdiv_node {
+			...
+		};
+
+		refoclk_node {
+			...
+		};
+		...
+	};
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : should be one of "microchip,pic32mzda-clk",
+    "microchip,pic32mzda-sosc", "microchip,pic32mzda-frcdivclk",
+    "microchip,pic32mzda-syspll", "microchip,pic32mzda-sysclk-v2",
+    "microchip,pic32mzda-pbclk", "microchip,pic32mzda-refoclk".
+- reg : A Base address and length of the register set.
+- interrupts : source of interrupt.
+
+Optional properties (for subnodes):
+- #clock-cells: From common clock binding, should be 0.
+- microchip,clock-indices: in multiplexer node clock sources always aren't linear
+    and contiguous. This property helps define clock-sources with respect to
+    the mux clock node.
+- microchip,ignore-unused : ignore gate request even if the gated clock is unused.
+- microchip,status-bit-mask: bitmask for status check. This will be used to confirm
+    particular operation by clock sub-node is completed. It is dependent sub-node.
+- microchip,bit-mask: enable mask, similar to microchip,status-bit-mask.
+- microchip,slew-step: enable frequency slewing(stepping) during rate change;
+    applicable only to sys-clock subnode.
+
+Example:
+
+/* PIC32 specific clks */
+pic32_clktree {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	reg = <0x1f801200 0x200>;
+	compatible = "microchip,pic32mzda-clk";
+	ranges = <0 0x1f801200 0x200>;
+
+	/* secondary oscillator; external input on SOSCI pin */
+	SOSC:sosc_clk {
+		#clock-cells = <0>;
+		compatible = "microchip,pic32mzda-sosc";
+		clock-frequency = <32768>;
+		reg = <0x000 0x10>, /* enable reg */
+		      <0x1d0 0x10>; /* status reg */
+		microchip,bit-mask = <0x02>; /* enable mask */
+		microchip,status-bit-mask = <0x10>; /* status-mask*/
+	};
+
+	FRCDIV:frcdiv_clk {
+		#clock-cells = <0>;
+		compatible = "microchip,pic32mzda-frcdivclk";
+		clocks = <&FRC>;
+		clock-output-names = "frcdiv_clk";
+	};
+
+	/* System PLL clock */
+	SYSPLL:spll_clk {
+		#clock-cells = <0>;
+		compatible = "microchip,pic32mzda-syspll";
+		reg = <0x020 0x10>, /* SPLL register */
+		      <0x1d0 0x10>; /* CLKSTAT register */
+		clocks = <&POSC>, <&FRC>;
+		clock-output-names = "sys_pll";
+		microchip,status-bit-mask = <0x80>; /* SPLLRDY */
+	};
+
+	/* system clock; mux with postdiv & slew */
+	SYSCLK:sys_clk {
+		#clock-cells = <0>;
+		compatible = "microchip,pic32mzda-sysclk-v2";
+		reg = <0x1c0 0x04>; /* SLEWCON */
+		clocks = <&FRCDIV>, <&SYSPLL>, <&POSC>, <&SOSC>,
+				<&LPRC>, <&FRCDIV>;
+		microchip,clock-indices = <0>, <1>, <2>, <4>, <5>, <7>;
+		clock-output-names = "sys_clk";
+	};
+
+	/* UPLL is integral part of USB PHY; UTMI clk for USBCORE */
+	UPLL:usb_phy_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clocks";
+		clock-frequency = <24000000>;
+		clock-output-names = "usbphy_clk";
+	};
+
+	/* Peripheral bus1 clock */
+	PBCLK1:pb1_clk {
+		reg = <0x140 0x10>;
+		#clock-cells = <0>;
+		compatible = "microchip,pic32mzda-pbclk";
+		clocks = <&SYSCLK>;
+		clock-output-names = "pb1_clk";
+		/* used by system modules, not gateable */
+		microchip,ignore-unused;
+	};
+
+	/* Peripheral bus2 clock */
+	PBCLK2:pb2_clk {
+		reg = <0x150 0x10>;
+		#clock-cells = <0>;
+		compatible = "microchip,pic32mzda-pbclk";
+		clocks = <&SYSCLK>;
+		clock-output-names = "pb2_clk";
+		/* avoid gating even if unused */
+		microchip,ignore-unused;
+	};
+
+	/* Peripheral bus3 clock */
+	PBCLK3:pb3_clk {
+		reg = <0x160 0x10>;
+		#clock-cells = <0>;
+		compatible = "microchip,pic32mzda-pbclk";
+		clocks = <&SYSCLK>;
+		clock-output-names = "pb3_clk";
+	};
+
+	/* Peripheral bus4 clock(I/O ports, GPIO) */
+	PBCLK4:pb4_clk {
+		reg = <0x170 0x10>;
+		#clock-cells = <0>;
+		compatible = "microchip,pic32mzda-pbclk";
+		clocks = <&SYSCLK>;
+		clock-output-names = "pb4_clk";
+	};
+
+	/* Peripheral bus clock */
+	PBCLK5:pb5_clk {
+		reg = <0x180 0x10>;
+		#clock-cells = <0>;
+		compatible = "microchip,pic32mzda-pbclk";
+		clocks = <&SYSCLK>;
+		clock-output-names = "pb5_clk";
+	};
+
+	/* Peripheral Bus6 clock; */
+	PBCLK6:pb6_clk {
+		reg = <0x190 0x10>;
+		compatible = "microchip,pic32mzda-pbclk";
+		clocks = <&SYSCLK>;
+		#clock-cells = <0>;
+	};
+
+	/* Peripheral bus7 clock */
+	PBCLK7:pb7_clk {
+		reg = <0x1A0 0x10>;
+		#clock-cells = <0>;
+		compatible = "microchip,pic32mzda-pbclk";
+		/* CPU is driven by this clock; so named */
+		clock-output-names = "cpu_clk";
+		clocks = <&SYSCLK>;
+	};
+
+	/* Reference Oscillator clock for SPI/I2S */
+	REFCLKO1:refo1_clk {
+		reg = <0x080 0x20>;
+		#clock-cells = <0>;
+		compatible = "microchip,pic32mzda-refoclk";
+		clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
+			<&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
+		microchip,clock-indices = <0>, <1>, <2>, <3>, <4>, <5>,
+						<7>, <8>, <9>;
+		clock-output-names = "refo1_clk";
+	};
+
+	/* Reference Oscillator clock for SQI */
+	REFCLKO2:refo2_clk {
+		reg = <0x0A0 0x20>;
+		#clock-cells = <0>;
+		compatible = "microchip,pic32mzda-refoclk";
+		clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
+			<&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
+		microchip,clock-indices = <0>, <1>, <2>, <3>, <4>, <5>,
+						<7>, <8>, <9>;
+		clock-output-names = "refo2_clk";
+	};
+
+	/* Reference Oscillator clock, ADC */
+	REFCLKO3:refo3_clk {
+		reg = <0x0C0 0x20>;
+		compatible = "microchip,pic32mzda-refoclk";
+		clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
+			<&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
+		microchip,clock-indices = <0>, <1>, <2>, <3>, <4>, <5>,
+						<7>, <8>, <9>;
+		#clock-cells = <0>;
+		clock-output-names = "refo3_clk";
+	};
+
+	/* Reference Oscillator clock */
+	REFCLKO4:refo4_clk {
+		reg = <0x0E0 0x20>;
+		compatible = "microchip,pic32mzda-refoclk";
+		clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
+				<&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
+		microchip,clock-indices = <0>,<1>,<2>,<3>,<4>,<5>,<7>,
+						<8>,<9>;
+		#clock-cells = <0>;
+		clock-output-names = "refo4_clk";
+	};
+
+	/* Reference Oscillator clock, LCD */
+	REFCLKO5:refo5_clk {
+		reg = <0x100 0x20>;
+		compatible = "microchip,pic32mzda-refoclk";
+		clocks = <&SYSCLK>,<&PBCLK1>,<&POSC>,<&FRC>,<&LPRC>,
+			<&SOSC>,<&SYSPLL>,<&REFIx>,<&BFRC>;
+		microchip,clock-indices = <0>, <1>, <2>, <3>, <4>, <5>,
+					<7>, <8>,<9>;
+		#clock-cells = <0>;
+		clock-output-names = "refo5_clk";
+	};
+};
+
+The clock consumer should specify the desired clock by having the clocks in its
+"clock" phandle cell. For example for UART:
+
+uart2: serial@<> {
+	compatible = "microchip,pic32mzda-uart";
+	reg = <>;
+	interrupts = <>;
+	clocks = <&PBCLK2>;
+}
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1294984 — Re: [PATCH v2 03/14] DEVICETREE: Add PIC32 clock binding documentation

FromRob Herring <robh@kernel.org>
Date2015-12-18 16:50 +0100
SubjectRe: [PATCH v2 03/14] DEVICETREE: Add PIC32 clock binding documentation
Message-ID<qH5s5-7vm-11@gated-at.bofh.it>
In reply to#1291650
On Mon, Dec 14, 2015 at 03:42:05PM -0700, Joshua Henderson wrote:
> From: Purna Chandra Mandal <purna.mandal@microchip.com>
> 
> Document the devicetree bindings for the clock driver found on Microchip
> PIC32 class devices.
> 
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> Signed-off-by: Joshua Henderson <joshua.henderson@microchip.com>
> Cc: Ralf Baechle <ralf@linux-mips.org>

A couple of nits on the example, otherwise:

Acked-by: Rob Herring <robh@kernel.org>

> ---
>  .../devicetree/bindings/clock/microchip,pic32.txt  |  256 ++++++++++++++++++++
>  1 file changed, 256 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/microchip,pic32.txt
> 
> diff --git a/Documentation/devicetree/bindings/clock/microchip,pic32.txt b/Documentation/devicetree/bindings/clock/microchip,pic32.txt
> new file mode 100644
> index 0000000..f50c653
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/microchip,pic32.txt
> @@ -0,0 +1,256 @@
> +Binding for a Clock hardware block found on
> +certain Microchip PIC32 MCU devices.
> +
> +Microchip SoC clocks-node consists of few oscillators, PLL, multiplexer
> +and few divider nodes.
> +
> +We will find only the base address of the clock tree, this base
> +address is common for some of the subnodes, not all. If no address is
> +specified for any of subnode base address of the clock tree will be
> +treated as its base. Each of subnodes follow the same common clock
> +binding with some additional optional properties.
> +
> +	clocks_node {
> +		reg = <>;
> +
> +		spll_node {
> +			...
> +		};
> +
> +		frcdiv_node {
> +			...
> +		};
> +
> +		sysclk_mux_node {
> +			...
> +		};
> +
> +		pbdiv_node {
> +			...
> +		};
> +
> +		refoclk_node {
> +			...
> +		};
> +		...
> +	};
> +
> +This binding uses the common clock binding[1].
> +
> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +Required properties:
> +- compatible : should be one of "microchip,pic32mzda-clk",
> +    "microchip,pic32mzda-sosc", "microchip,pic32mzda-frcdivclk",
> +    "microchip,pic32mzda-syspll", "microchip,pic32mzda-sysclk-v2",
> +    "microchip,pic32mzda-pbclk", "microchip,pic32mzda-refoclk".
> +- reg : A Base address and length of the register set.
> +- interrupts : source of interrupt.
> +
> +Optional properties (for subnodes):
> +- #clock-cells: From common clock binding, should be 0.
> +- microchip,clock-indices: in multiplexer node clock sources always aren't linear
> +    and contiguous. This property helps define clock-sources with respect to
> +    the mux clock node.
> +- microchip,ignore-unused : ignore gate request even if the gated clock is unused.
> +- microchip,status-bit-mask: bitmask for status check. This will be used to confirm
> +    particular operation by clock sub-node is completed. It is dependent sub-node.
> +- microchip,bit-mask: enable mask, similar to microchip,status-bit-mask.
> +- microchip,slew-step: enable frequency slewing(stepping) during rate change;
> +    applicable only to sys-clock subnode.
> +
> +Example:
> +
> +/* PIC32 specific clks */
> +pic32_clktree {
> +	#address-cells = <1>;
> +	#size-cells = <1>;
> +	reg = <0x1f801200 0x200>;
> +	compatible = "microchip,pic32mzda-clk";
> +	ranges = <0 0x1f801200 0x200>;
> +
> +	/* secondary oscillator; external input on SOSCI pin */
> +	SOSC:sosc_clk {

For the ones with reg property, do clock@0 instead of sosc_clk.

> +		#clock-cells = <0>;
> +		compatible = "microchip,pic32mzda-sosc";
> +		clock-frequency = <32768>;
> +		reg = <0x000 0x10>, /* enable reg */
> +		      <0x1d0 0x10>; /* status reg */
> +		microchip,bit-mask = <0x02>; /* enable mask */
> +		microchip,status-bit-mask = <0x10>; /* status-mask*/
> +	};
> +
> +	FRCDIV:frcdiv_clk {
> +		#clock-cells = <0>;
> +		compatible = "microchip,pic32mzda-frcdivclk";
> +		clocks = <&FRC>;
> +		clock-output-names = "frcdiv_clk";
> +	};
> +
> +	/* System PLL clock */
> +	SYSPLL:spll_clk {
> +		#clock-cells = <0>;
> +		compatible = "microchip,pic32mzda-syspll";
> +		reg = <0x020 0x10>, /* SPLL register */
> +		      <0x1d0 0x10>; /* CLKSTAT register */
> +		clocks = <&POSC>, <&FRC>;
> +		clock-output-names = "sys_pll";
> +		microchip,status-bit-mask = <0x80>; /* SPLLRDY */
> +	};
> +
> +	/* system clock; mux with postdiv & slew */
> +	SYSCLK:sys_clk {
> +		#clock-cells = <0>;
> +		compatible = "microchip,pic32mzda-sysclk-v2";
> +		reg = <0x1c0 0x04>; /* SLEWCON */
> +		clocks = <&FRCDIV>, <&SYSPLL>, <&POSC>, <&SOSC>,
> +				<&LPRC>, <&FRCDIV>;
> +		microchip,clock-indices = <0>, <1>, <2>, <4>, <5>, <7>;
> +		clock-output-names = "sys_clk";
> +	};
> +
> +	/* UPLL is integral part of USB PHY; UTMI clk for USBCORE */
> +	UPLL:usb_phy_clk {
> +		#clock-cells = <0>;
> +		compatible = "fixed-clocks";
> +		clock-frequency = <24000000>;
> +		clock-output-names = "usbphy_clk";
> +	};
> +
> +	/* Peripheral bus1 clock */
> +	PBCLK1:pb1_clk {
> +		reg = <0x140 0x10>;
> +		#clock-cells = <0>;
> +		compatible = "microchip,pic32mzda-pbclk";
> +		clocks = <&SYSCLK>;
> +		clock-output-names = "pb1_clk";
> +		/* used by system modules, not gateable */
> +		microchip,ignore-unused;
> +	};
> +
> +	/* Peripheral bus2 clock */
> +	PBCLK2:pb2_clk {
> +		reg = <0x150 0x10>;
> +		#clock-cells = <0>;
> +		compatible = "microchip,pic32mzda-pbclk";
> +		clocks = <&SYSCLK>;
> +		clock-output-names = "pb2_clk";
> +		/* avoid gating even if unused */
> +		microchip,ignore-unused;
> +	};
> +
> +	/* Peripheral bus3 clock */
> +	PBCLK3:pb3_clk {
> +		reg = <0x160 0x10>;
> +		#clock-cells = <0>;
> +		compatible = "microchip,pic32mzda-pbclk";
> +		clocks = <&SYSCLK>;
> +		clock-output-names = "pb3_clk";
> +	};
> +
> +	/* Peripheral bus4 clock(I/O ports, GPIO) */
> +	PBCLK4:pb4_clk {
> +		reg = <0x170 0x10>;
> +		#clock-cells = <0>;
> +		compatible = "microchip,pic32mzda-pbclk";
> +		clocks = <&SYSCLK>;
> +		clock-output-names = "pb4_clk";
> +	};
> +
> +	/* Peripheral bus clock */
> +	PBCLK5:pb5_clk {
> +		reg = <0x180 0x10>;
> +		#clock-cells = <0>;
> +		compatible = "microchip,pic32mzda-pbclk";
> +		clocks = <&SYSCLK>;
> +		clock-output-names = "pb5_clk";
> +	};
> +
> +	/* Peripheral Bus6 clock; */
> +	PBCLK6:pb6_clk {
> +		reg = <0x190 0x10>;
> +		compatible = "microchip,pic32mzda-pbclk";
> +		clocks = <&SYSCLK>;
> +		#clock-cells = <0>;
> +	};
> +
> +	/* Peripheral bus7 clock */
> +	PBCLK7:pb7_clk {
> +		reg = <0x1A0 0x10>;

lower case

> +		#clock-cells = <0>;
> +		compatible = "microchip,pic32mzda-pbclk";
> +		/* CPU is driven by this clock; so named */
> +		clock-output-names = "cpu_clk";
> +		clocks = <&SYSCLK>;
> +	};
> +
> +	/* Reference Oscillator clock for SPI/I2S */
> +	REFCLKO1:refo1_clk {
> +		reg = <0x080 0x20>;
> +		#clock-cells = <0>;
> +		compatible = "microchip,pic32mzda-refoclk";
> +		clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
> +			<&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
> +		microchip,clock-indices = <0>, <1>, <2>, <3>, <4>, <5>,
> +						<7>, <8>, <9>;
> +		clock-output-names = "refo1_clk";
> +	};
> +
> +	/* Reference Oscillator clock for SQI */
> +	REFCLKO2:refo2_clk {
> +		reg = <0x0A0 0x20>;

lower case

> +		#clock-cells = <0>;
> +		compatible = "microchip,pic32mzda-refoclk";
> +		clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
> +			<&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
> +		microchip,clock-indices = <0>, <1>, <2>, <3>, <4>, <5>,
> +						<7>, <8>, <9>;
> +		clock-output-names = "refo2_clk";
> +	};
> +
> +	/* Reference Oscillator clock, ADC */
> +	REFCLKO3:refo3_clk {
> +		reg = <0x0C0 0x20>;

lower case

> +		compatible = "microchip,pic32mzda-refoclk";
> +		clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
> +			<&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
> +		microchip,clock-indices = <0>, <1>, <2>, <3>, <4>, <5>,
> +						<7>, <8>, <9>;
> +		#clock-cells = <0>;
> +		clock-output-names = "refo3_clk";
> +	};
> +
> +	/* Reference Oscillator clock */
> +	REFCLKO4:refo4_clk {
> +		reg = <0x0E0 0x20>;
> +		compatible = "microchip,pic32mzda-refoclk";
> +		clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
> +				<&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
> +		microchip,clock-indices = <0>,<1>,<2>,<3>,<4>,<5>,<7>,
> +						<8>,<9>;
> +		#clock-cells = <0>;
> +		clock-output-names = "refo4_clk";
> +	};
> +
> +	/* Reference Oscillator clock, LCD */
> +	REFCLKO5:refo5_clk {
> +		reg = <0x100 0x20>;
> +		compatible = "microchip,pic32mzda-refoclk";
> +		clocks = <&SYSCLK>,<&PBCLK1>,<&POSC>,<&FRC>,<&LPRC>,
> +			<&SOSC>,<&SYSPLL>,<&REFIx>,<&BFRC>;
> +		microchip,clock-indices = <0>, <1>, <2>, <3>, <4>, <5>,
> +					<7>, <8>,<9>;
> +		#clock-cells = <0>;
> +		clock-output-names = "refo5_clk";
> +	};
> +};
> +
> +The clock consumer should specify the desired clock by having the clocks in its
> +"clock" phandle cell. For example for UART:
> +
> +uart2: serial@<> {
> +	compatible = "microchip,pic32mzda-uart";
> +	reg = <>;
> +	interrupts = <>;
> +	clocks = <&PBCLK2>;
> +}
> -- 
> 1.7.9.5
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1295367 — Re: [PATCH v2 03/14] DEVICETREE: Add PIC32 clock binding documentation

FromPurna Chandra Mandal <purna.mandal@microchip.com>
Date2015-12-19 13:00 +0100
SubjectRe: [PATCH v2 03/14] DEVICETREE: Add PIC32 clock binding documentation
Message-ID<qHol3-2HU-3@gated-at.bofh.it>
In reply to#1294984
On 12/18/2015 09:14 PM, Rob Herring wrote:
> On Mon, Dec 14, 2015 at 03:42:05PM -0700, Joshua Henderson wrote:
>> From: Purna Chandra Mandal <purna.mandal@microchip.com>
>>
>> Document the devicetree bindings for the clock driver found on Microchip
>> PIC32 class devices.
>>
>> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
>> Signed-off-by: Joshua Henderson <joshua.henderson@microchip.com>
>> Cc: Ralf Baechle <ralf@linux-mips.org>
> A couple of nits on the example, otherwise:
>
> Acked-by: Rob Herring <robh@kernel.org>
>
>> ---
>>  .../devicetree/bindings/clock/microchip,pic32.txt  |  256 ++++++++++++++++++++
>>  1 file changed, 256 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/clock/microchip,pic32.txt
>>
>> diff --git a/Documentation/devicetree/bindings/clock/microchip,pic32.txt b/Documentation/devicetree/bindings/clock/microchip,pic32.txt
>> new file mode 100644
>> index 0000000..f50c653
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/microchip,pic32.txt
>> @@ -0,0 +1,256 @@
>> +Binding for a Clock hardware block found on
>> +certain Microchip PIC32 MCU devices.
>> +
>> +Microchip SoC clocks-node consists of few oscillators, PLL, multiplexer
>> +and few divider nodes.
>> +
>> +We will find only the base address of the clock tree, this base
>> +address is common for some of the subnodes, not all. If no address is
>> +specified for any of subnode base address of the clock tree will be
>> +treated as its base. Each of subnodes follow the same common clock
>> +binding with some additional optional properties.
>> +
>> +	clocks_node {
>> +		reg = <>;
>> +
>> +		spll_node {
>> +			...
>> +		};
>> +
>> +		frcdiv_node {
>> +			...
>> +		};
>> +
>> +		sysclk_mux_node {
>> +			...
>> +		};
>> +
>> +		pbdiv_node {
>> +			...
>> +		};
>> +
>> +		refoclk_node {
>> +			...
>> +		};
>> +		...
>> +	};
>> +
>> +This binding uses the common clock binding[1].
>> +
>> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
>> +
>> +Required properties:
>> +- compatible : should be one of "microchip,pic32mzda-clk",
>> +    "microchip,pic32mzda-sosc", "microchip,pic32mzda-frcdivclk",
>> +    "microchip,pic32mzda-syspll", "microchip,pic32mzda-sysclk-v2",
>> +    "microchip,pic32mzda-pbclk", "microchip,pic32mzda-refoclk".
>> +- reg : A Base address and length of the register set.
>> +- interrupts : source of interrupt.
>> +
>> +Optional properties (for subnodes):
>> +- #clock-cells: From common clock binding, should be 0.
>> +- microchip,clock-indices: in multiplexer node clock sources always aren't linear
>> +    and contiguous. This property helps define clock-sources with respect to
>> +    the mux clock node.
>> +- microchip,ignore-unused : ignore gate request even if the gated clock is unused.
>> +- microchip,status-bit-mask: bitmask for status check. This will be used to confirm
>> +    particular operation by clock sub-node is completed. It is dependent sub-node.
>> +- microchip,bit-mask: enable mask, similar to microchip,status-bit-mask.
>> +- microchip,slew-step: enable frequency slewing(stepping) during rate change;
>> +    applicable only to sys-clock subnode.
>> +
>> +Example:
>> +
>> +/* PIC32 specific clks */
>> +pic32_clktree {
>> +	#address-cells = <1>;
>> +	#size-cells = <1>;
>> +	reg = <0x1f801200 0x200>;
>> +	compatible = "microchip,pic32mzda-clk";
>> +	ranges = <0 0x1f801200 0x200>;
>> +
>> +	/* secondary oscillator; external input on SOSCI pin */
>> +	SOSC:sosc_clk {
> For the ones with reg property, do clock@0 instead of sosc_clk.

ack. Will update.

>> +		#clock-cells = <0>;
>> +		compatible = "microchip,pic32mzda-sosc";
>> +		clock-frequency = <32768>;
>> +		reg = <0x000 0x10>, /* enable reg */
>> +		      <0x1d0 0x10>; /* status reg */
>> +		microchip,bit-mask = <0x02>; /* enable mask */
>> +		microchip,status-bit-mask = <0x10>; /* status-mask*/
>> +	};
>> +
>> +	FRCDIV:frcdiv_clk {
>> +		#clock-cells = <0>;
>> +		compatible = "microchip,pic32mzda-frcdivclk";
>> +		clocks = <&FRC>;
>> +		clock-output-names = "frcdiv_clk";
>> +	};
>> +
>> +	/* System PLL clock */
>> +	SYSPLL:spll_clk {
>> +		#clock-cells = <0>;
>> +		compatible = "microchip,pic32mzda-syspll";
>> +		reg = <0x020 0x10>, /* SPLL register */
>> +		      <0x1d0 0x10>; /* CLKSTAT register */
>> +		clocks = <&POSC>, <&FRC>;
>> +		clock-output-names = "sys_pll";
>> +		microchip,status-bit-mask = <0x80>; /* SPLLRDY */
>> +	};
>> +
>> +	/* system clock; mux with postdiv & slew */
>> +	SYSCLK:sys_clk {
>> +		#clock-cells = <0>;
>> +		compatible = "microchip,pic32mzda-sysclk-v2";
>> +		reg = <0x1c0 0x04>; /* SLEWCON */
>> +		clocks = <&FRCDIV>, <&SYSPLL>, <&POSC>, <&SOSC>,
>> +				<&LPRC>, <&FRCDIV>;
>> +		microchip,clock-indices = <0>, <1>, <2>, <4>, <5>, <7>;
>> +		clock-output-names = "sys_clk";
>> +	};
>> +
>> +	/* UPLL is integral part of USB PHY; UTMI clk for USBCORE */
>> +	UPLL:usb_phy_clk {
>> +		#clock-cells = <0>;
>> +		compatible = "fixed-clocks";
>> +		clock-frequency = <24000000>;
>> +		clock-output-names = "usbphy_clk";
>> +	};
>> +
>> +	/* Peripheral bus1 clock */
>> +	PBCLK1:pb1_clk {
>> +		reg = <0x140 0x10>;
>> +		#clock-cells = <0>;
>> +		compatible = "microchip,pic32mzda-pbclk";
>> +		clocks = <&SYSCLK>;
>> +		clock-output-names = "pb1_clk";
>> +		/* used by system modules, not gateable */
>> +		microchip,ignore-unused;
>> +	};
>> +
>> +	/* Peripheral bus2 clock */
>> +	PBCLK2:pb2_clk {
>> +		reg = <0x150 0x10>;
>> +		#clock-cells = <0>;
>> +		compatible = "microchip,pic32mzda-pbclk";
>> +		clocks = <&SYSCLK>;
>> +		clock-output-names = "pb2_clk";
>> +		/* avoid gating even if unused */
>> +		microchip,ignore-unused;
>> +	};
>> +
>> +	/* Peripheral bus3 clock */
>> +	PBCLK3:pb3_clk {
>> +		reg = <0x160 0x10>;
>> +		#clock-cells = <0>;
>> +		compatible = "microchip,pic32mzda-pbclk";
>> +		clocks = <&SYSCLK>;
>> +		clock-output-names = "pb3_clk";
>> +	};
>> +
>> +	/* Peripheral bus4 clock(I/O ports, GPIO) */
>> +	PBCLK4:pb4_clk {
>> +		reg = <0x170 0x10>;
>> +		#clock-cells = <0>;
>> +		compatible = "microchip,pic32mzda-pbclk";
>> +		clocks = <&SYSCLK>;
>> +		clock-output-names = "pb4_clk";
>> +	};
>> +
>> +	/* Peripheral bus clock */
>> +	PBCLK5:pb5_clk {
>> +		reg = <0x180 0x10>;
>> +		#clock-cells = <0>;
>> +		compatible = "microchip,pic32mzda-pbclk";
>> +		clocks = <&SYSCLK>;
>> +		clock-output-names = "pb5_clk";
>> +	};
>> +
>> +	/* Peripheral Bus6 clock; */
>> +	PBCLK6:pb6_clk {
>> +		reg = <0x190 0x10>;
>> +		compatible = "microchip,pic32mzda-pbclk";
>> +		clocks = <&SYSCLK>;
>> +		#clock-cells = <0>;
>> +	};
>> +
>> +	/* Peripheral bus7 clock */
>> +	PBCLK7:pb7_clk {
>> +		reg = <0x1A0 0x10>;
> lower case

ack.

>> +		#clock-cells = <0>;
>> +		compatible = "microchip,pic32mzda-pbclk";
>> +		/* CPU is driven by this clock; so named */
>> +		clock-output-names = "cpu_clk";
>> +		clocks = <&SYSCLK>;
>> +	};
>> +
>> +	/* Reference Oscillator clock for SPI/I2S */
>> +	REFCLKO1:refo1_clk {
>> +		reg = <0x080 0x20>;
>> +		#clock-cells = <0>;
>> +		compatible = "microchip,pic32mzda-refoclk";
>> +		clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
>> +			<&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
>> +		microchip,clock-indices = <0>, <1>, <2>, <3>, <4>, <5>,
>> +						<7>, <8>, <9>;
>> +		clock-output-names = "refo1_clk";
>> +	};
>> +
>> +	/* Reference Oscillator clock for SQI */
>> +	REFCLKO2:refo2_clk {
>> +		reg = <0x0A0 0x20>;
> lower case

ack.

>> +		#clock-cells = <0>;
>> +		compatible = "microchip,pic32mzda-refoclk";
>> +		clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
>> +			<&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
>> +		microchip,clock-indices = <0>, <1>, <2>, <3>, <4>, <5>,
>> +						<7>, <8>, <9>;
>> +		clock-output-names = "refo2_clk";
>> +	};
>> +
>> +	/* Reference Oscillator clock, ADC */
>> +	REFCLKO3:refo3_clk {
>> +		reg = <0x0C0 0x20>;
> lower case

ack.

>> +		compatible = "microchip,pic32mzda-refoclk";
>> +		clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
>> +			<&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
>> +		microchip,clock-indices = <0>, <1>, <2>, <3>, <4>, <5>,
>> +						<7>, <8>, <9>;
>> +		#clock-cells = <0>;
>> +		clock-output-names = "refo3_clk";
>> +	};
>> +
>> +	/* Reference Oscillator clock */
>> +	REFCLKO4:refo4_clk {
>> +		reg = <0x0E0 0x20>;
>> +		compatible = "microchip,pic32mzda-refoclk";
>> +		clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
>> +				<&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
>> +		microchip,clock-indices = <0>,<1>,<2>,<3>,<4>,<5>,<7>,
>> +						<8>,<9>;
>> +		#clock-cells = <0>;
>> +		clock-output-names = "refo4_clk";
>> +	};
>> +
>> +	/* Reference Oscillator clock, LCD */
>> +	REFCLKO5:refo5_clk {
>> +		reg = <0x100 0x20>;
>> +		compatible = "microchip,pic32mzda-refoclk";
>> +		clocks = <&SYSCLK>,<&PBCLK1>,<&POSC>,<&FRC>,<&LPRC>,
>> +			<&SOSC>,<&SYSPLL>,<&REFIx>,<&BFRC>;
>> +		microchip,clock-indices = <0>, <1>, <2>, <3>, <4>, <5>,
>> +					<7>, <8>,<9>;
>> +		#clock-cells = <0>;
>> +		clock-output-names = "refo5_clk";
>> +	};
>> +};
>> +
>> +The clock consumer should specify the desired clock by having the clocks in its
>> +"clock" phandle cell. For example for UART:
>> +
>> +uart2: serial@<> {
>> +	compatible = "microchip,pic32mzda-uart";
>> +	reg = <>;
>> +	interrupts = <>;
>> +	clocks = <&PBCLK2>;
>> +}
>> -- 
>> 1.7.9.5
>>

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1291653 — [PATCH v2 01/14] DEVICETREE: Add bindings for PIC32 interrupt controller

FromJoshua Henderson <joshua.henderson@microchip.com>
Date2015-12-14 23:50 +0100
Subject[PATCH v2 01/14] DEVICETREE: Add bindings for PIC32 interrupt controller
Message-ID<qFK6m-3W4-13@gated-at.bofh.it>
In reply to#1291644
From: Cristian Birsan <cristian.birsan@microchip.com>

Document the devicetree bindings for the interrupt controller on
Microchip PIC32 class devices.

Signed-off-by: Cristian Birsan <cristian.birsan@microchip.com>
Signed-off-by: Joshua Henderson <joshua.henderson@microchip.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
---
 .../interrupt-controller/microchip,pic32-evic.txt  |   58 ++++++++++++++++++++
 1 file changed, 58 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/microchip,pic32-evic.txt

diff --git a/Documentation/devicetree/bindings/interrupt-controller/microchip,pic32-evic.txt b/Documentation/devicetree/bindings/interrupt-controller/microchip,pic32-evic.txt
new file mode 100644
index 0000000..6f4389a
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/microchip,pic32-evic.txt
@@ -0,0 +1,58 @@
+Microchip PIC32 Interrupt Controller
+====================================
+
+The Microchip PIC32 contains an Enhanced Vectored Interrupt Controller
+(EVIC). It handles internal and external interrupts and provides support for
+irq type and polarity.
+
+Required properties
+-------------------
+
+- compatible: Should be "microchip,pic32mzda-evic"
+
+- reg: Specifies physical base address and size of register range.
+
+- interrupt-controller: Identifies the node as an interrupt controller.
+
+- #interrupt cells: Specifies the number of cells used to encode an interrupt
+source connected to this controller. The value shall be 2 and interrupt
+descriptor shall have the following format:
+	<hw_irq irq_type>
+
+hw_irq - represents the hardware interrupt number as in the data sheet.
+
+irq_type - is used to describe the type and polarity of an interrupt. For
+internal interrupts use IRQ_TYPE_EDGE_RISING for non persistent interrupts and
+IRQ_TYPE_LEVEL_HIGH for persistent interrupts. For external interrupts use
+IRQ_TYPE_EDGE_RISING or IRQ_TYPE_EDGE_FALLING to select the desired polarity.
+
+Example
+-------
+
+evic: interrupt-controller@1f810000 {
+        compatible = "microchip,pic32mzda-evic";
+        interrupt-controller;
+        #interrupt-cells = <2>;
+        reg = <0x1f810000 0x1000>;
+};
+
+Each device must request his interrupt line with the associated priority and
+polarity
+
+Internal interrupt DTS snippet
+------------------------------
+
+device@1f800000 {
+	...
+	interrupts = <113 IRQ_TYPE_LEVEL_HIGH>;
+	...
+};
+
+External interrupt DTS snippet
+------------------------------
+
+device@1f800000 {
+	...
+	interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+	...
+};
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1291691 — Re: [PATCH v2 01/14] DEVICETREE: Add bindings for PIC32 interrupt controller

FromRob Herring <robh@kernel.org>
Date2015-12-15 00:40 +0100
SubjectRe: [PATCH v2 01/14] DEVICETREE: Add bindings for PIC32 interrupt controller
Message-ID<qFKSL-4sB-51@gated-at.bofh.it>
In reply to#1291653
On Mon, Dec 14, 2015 at 03:42:03PM -0700, Joshua Henderson wrote:
> From: Cristian Birsan <cristian.birsan@microchip.com>
> 
> Document the devicetree bindings for the interrupt controller on
> Microchip PIC32 class devices.
> 
> Signed-off-by: Cristian Birsan <cristian.birsan@microchip.com>
> Signed-off-by: Joshua Henderson <joshua.henderson@microchip.com>
> Cc: Ralf Baechle <ralf@linux-mips.org>

Acked-by: Rob Herring <robh@kernel.org>

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1291656 — [PATCH v2 13/14] MIPS: dts: Add initial DTS for the PIC32MZDA Starter Kit

FromJoshua Henderson <joshua.henderson@microchip.com>
Date2015-12-14 23:50 +0100
Subject[PATCH v2 13/14] MIPS: dts: Add initial DTS for the PIC32MZDA Starter Kit
Message-ID<qFK6m-3W4-29@gated-at.bofh.it>
In reply to#1291644
This adds basic DTS configuration for the PIC32MZDA chip and in turn the
PIC32MZDA Starter Kit.

Signed-off-by: Joshua Henderson <joshua.henderson@microchip.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
---
 arch/mips/boot/dts/Makefile                 |    1 +
 arch/mips/boot/dts/pic32/Makefile           |   12 ++
 arch/mips/boot/dts/pic32/pic32mzda-clk.dtsi |  235 +++++++++++++++++++++++
 arch/mips/boot/dts/pic32/pic32mzda.dtsi     |  275 +++++++++++++++++++++++++++
 arch/mips/boot/dts/pic32/pic32mzda_sk.dts   |  151 +++++++++++++++
 arch/mips/pic32/Kconfig                     |   16 ++
 6 files changed, 690 insertions(+)
 create mode 100644 arch/mips/boot/dts/pic32/Makefile
 create mode 100644 arch/mips/boot/dts/pic32/pic32mzda-clk.dtsi
 create mode 100644 arch/mips/boot/dts/pic32/pic32mzda.dtsi
 create mode 100644 arch/mips/boot/dts/pic32/pic32mzda_sk.dts

diff --git a/arch/mips/boot/dts/Makefile b/arch/mips/boot/dts/Makefile
index a0bf516..fc7a0a9 100644
--- a/arch/mips/boot/dts/Makefile
+++ b/arch/mips/boot/dts/Makefile
@@ -4,6 +4,7 @@ dts-dirs	+= ingenic
 dts-dirs	+= lantiq
 dts-dirs	+= mti
 dts-dirs	+= netlogic
+dts-dirs	+= pic32
 dts-dirs	+= qca
 dts-dirs	+= ralink
 dts-dirs	+= xilfpga
diff --git a/arch/mips/boot/dts/pic32/Makefile b/arch/mips/boot/dts/pic32/Makefile
new file mode 100644
index 0000000..7ac7905
--- /dev/null
+++ b/arch/mips/boot/dts/pic32/Makefile
@@ -0,0 +1,12 @@
+dtb-$(CONFIG_DTB_PIC32_MZDA_SK)		+= pic32mzda_sk.dtb
+
+dtb-$(CONFIG_DTB_PIC32_NONE)		+= \
+					pic32mzda_sk.dtb
+
+obj-y				+= $(patsubst %.dtb, %.dtb.o, $(dtb-y))
+
+# Force kbuild to make empty built-in.o if necessary
+obj-				+= dummy.o
+
+always				:= $(dtb-y)
+clean-files			:= *.dtb *.dtb.S
diff --git a/arch/mips/boot/dts/pic32/pic32mzda-clk.dtsi b/arch/mips/boot/dts/pic32/pic32mzda-clk.dtsi
new file mode 100644
index 0000000..9ab4df8
--- /dev/null
+++ b/arch/mips/boot/dts/pic32/pic32mzda-clk.dtsi
@@ -0,0 +1,235 @@
+/*
+ * Device Tree Source for PIC32MZDA clock data
+ *
+ * Purna Chandra Mandal <purna.mandal@microchip.com>
+ * Copyright (C) 2015 Microchip Technology Inc.  All rights reserved.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/* all fixed rate clocks */
+
+/ {
+	POSC:posc_clk { /* On-chip primary oscillator */
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+	};
+
+	FRC:frc_clk { /* internal FRC oscillator */
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <8000000>;
+	};
+
+	BFRC:bfrc_clk { /* internal backup FRC oscillator */
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <8000000>;
+	};
+
+	LPRC:lprc_clk { /* internal low-power FRC oscillator */
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32000>;
+	};
+
+	/* UPLL provides UTMI clock to USBCORE */
+	UPLL:usb_phy_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "usbphy_clk";
+	};
+
+	TxCKI:txcki_clk { /* external clock input on TxCLKI pin */
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <4000000>;
+		status = "disabled";
+	};
+
+	/* external clock input on REFCLKIx pin */
+	REFIx:refix_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		status = "disabled";
+	};
+
+	/* PIC32 specific clks */
+	pic32_clktree {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x1f801200 0x200>;
+		compatible = "microchip,pic32mzda-clk";
+		ranges = <0 0x1f801200 0x200>;
+
+		/* secondary oscillator; external input on SOSCI pin */
+		SOSC:sosc_clk {
+			#clock-cells = <0>;
+			compatible = "microchip,pic32mzda-sosc";
+			clock-frequency = <32768>;
+			reg = <0x000 0x10>,   /* enable reg */
+			      <0x1d0 0x10>; /* status reg */
+			microchip,bit-mask = <0x02>; /* enable mask */
+			microchip,status-bit-mask = <0x10>; /* status-mask*/
+		};
+
+		FRCDIV:frcdiv_clk {
+			#clock-cells = <0>;
+			compatible = "microchip,pic32mzda-frcdivclk";
+			clocks = <&FRC>;
+			clock-output-names = "frcdiv_clk";
+		};
+
+		/* System PLL clock */
+		SYSPLL:spll_clk {
+			#clock-cells = <0>;
+			compatible = "microchip,pic32mzda-syspll";
+			reg = <0x020 0x10>, /* SPLL register */
+			      <0x1d0 0x10>; /* CLKSTAT register */
+			clocks = <&POSC>, <&FRC>;
+			clock-output-names = "sys_pll";
+			microchip,status-bit-mask = <0x80>; /* SPLLRDY */
+		};
+
+		/* system clock; mux with postdiv & slew */
+		SYSCLK:sys_clk {
+			#clock-cells = <0>;
+			compatible = "microchip,pic32mzda-sysclk-v2";
+			reg = <0x1c0 0x04>; /* SLEWCON */
+			clocks = <&FRCDIV>, <&SYSPLL>, <&POSC>, <&SOSC>,
+				 <&LPRC>, <&FRCDIV>;
+			microchip,clock-indices = <0>, <1>, <2>, <4>, <5>, <7>;
+			clock-output-names = "sys_clk";
+		};
+
+		/* Peripheral bus1 clock */
+		PBCLK1:pb1_clk {
+			reg = <0x140 0x10>;
+			#clock-cells = <0>;
+			compatible = "microchip,pic32mzda-pbclk";
+			clocks = <&SYSCLK>;
+			clock-output-names = "pb1_clk";
+			/* used by system modules, not gateable */
+			microchip,ignore-unused;
+		};
+
+		/* Peripheral bus2 clock */
+		PBCLK2:pb2_clk {
+			reg = <0x150 0x10>;
+			#clock-cells = <0>;
+			compatible = "microchip,pic32mzda-pbclk";
+			clocks = <&SYSCLK>;
+			clock-output-names = "pb2_clk";
+			/* avoid gating even if unused */
+			microchip,ignore-unused;
+		};
+
+		/* Peripheral bus3 clock */
+		PBCLK3:pb3_clk {
+			reg = <0x160 0x10>;
+			#clock-cells = <0>;
+			compatible = "microchip,pic32mzda-pbclk";
+			clocks = <&SYSCLK>;
+			clock-output-names = "pb3_clk";
+		};
+
+		/* Peripheral bus4 clock(I/O ports, GPIO) */
+		PBCLK4:pb4_clk {
+			reg = <0x170 0x10>;
+			#clock-cells = <0>;
+			compatible = "microchip,pic32mzda-pbclk";
+			clocks = <&SYSCLK>;
+			clock-output-names = "pb4_clk";
+		};
+
+		/* Peripheral bus clock */
+		PBCLK5:pb5_clk {
+			reg = <0x180 0x10>;
+			#clock-cells = <0>;
+			compatible = "microchip,pic32mzda-pbclk";
+			clocks = <&SYSCLK>;
+			clock-output-names = "pb5_clk";
+		};
+
+		/* Peripheral Bus6 clock; */
+		PBCLK6:pb6_clk {
+			reg = <0x190 0x10>;
+			compatible = "microchip,pic32mzda-pbclk";
+			clocks = <&SYSCLK>;
+			#clock-cells = <0>;
+		};
+
+		/* Peripheral bus7 clock */
+		PBCLK7:pb7_clk {
+			reg = <0x1A0 0x10>;
+			#clock-cells = <0>;
+			compatible = "microchip,pic32mzda-pbclk";
+			/* CPU is driven by this clock; so named */
+			clock-output-names = "cpu_clk";
+			clocks = <&SYSCLK>;
+		};
+
+		/* Reference Oscillator clock for SPI/I2S */
+		REFCLKO1:refo1_clk {
+			reg = <0x080 0x20>;
+			#clock-cells = <0>;
+			compatible = "microchip,pic32mzda-refoclk";
+			clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
+				<&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
+			microchip,clock-indices = <0>, <1>, <2>, <3>, <4>,
+						  <5>, <7>, <8>, <9>;
+			clock-output-names = "refo1_clk";
+		};
+
+		/* Reference Oscillator clock for SQI */
+		REFCLKO2:refo2_clk {
+			reg = <0x0A0 0x20>;
+			#clock-cells = <0>;
+			compatible = "microchip,pic32mzda-refoclk";
+			clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
+				<&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
+			microchip,clock-indices = <0>, <1>, <2>, <3>, <4>,
+						  <5>, <7>, <8>, <9>;
+			clock-output-names = "refo2_clk";
+		};
+
+		/* Reference Oscillator clock, ADC */
+		REFCLKO3:refo3_clk {
+			reg = <0x0C0 0x20>;
+			compatible = "microchip,pic32mzda-refoclk";
+			clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
+				<&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
+			microchip,clock-indices = <0>, <1>, <2>, <3>, <4>,
+						  <5>, <7>, <8>, <9>;
+			#clock-cells = <0>;
+			clock-output-names = "refo3_clk";
+		};
+
+		/* Reference Oscillator clock */
+		REFCLKO4:refo4_clk {
+			reg = <0x0E0 0x20>;
+			compatible = "microchip,pic32mzda-refoclk";
+			clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
+					<&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
+			microchip,clock-indices = <0>, <1>, <2>, <3>, <4>,
+						  <5>, <7>, <8>, <9>;
+			#clock-cells = <0>;
+			clock-output-names = "refo4_clk";
+		};
+
+		/* Reference Oscillator clock, LCD */
+		REFCLKO5:refo5_clk {
+			reg = <0x100 0x20>;
+			compatible = "microchip,pic32mzda-refoclk";
+			clocks = <&SYSCLK>,<&PBCLK1>,<&POSC>,<&FRC>,<&LPRC>,
+				<&SOSC>,<&SYSPLL>,<&REFIx>,<&BFRC>;
+			microchip,clock-indices = <0>, <1>, <2>, <3>, <4>,
+						  <5>, <7>, <8>, <9>;
+			#clock-cells = <0>;
+			clock-output-names = "refo5_clk";
+		};
+	};
+};
diff --git a/arch/mips/boot/dts/pic32/pic32mzda.dtsi b/arch/mips/boot/dts/pic32/pic32mzda.dtsi
new file mode 100644
index 0000000..3eee106
--- /dev/null
+++ b/arch/mips/boot/dts/pic32/pic32mzda.dtsi
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2015 Microchip Technology Inc.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#include "pic32mzda-clk.dtsi"
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&evic>;
+
+	aliases {
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+		gpio2 = &gpio2;
+		gpio3 = &gpio3;
+		gpio4 = &gpio4;
+		gpio5 = &gpio5;
+		gpio6 = &gpio6;
+		gpio7 = &gpio7;
+		gpio8 = &gpio8;
+		gpio9 = &gpio9;
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+		serial3 = &uart4;
+		serial4 = &uart5;
+		serial5 = &uart6;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "mti,mips14KEc";
+			device_type = "cpu";
+		};
+	};
+
+	evic: interrupt-controller@1f810000 {
+		compatible = "microchip,pic32mzda-evic";
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		reg = <0x1f810000 0x1000>;
+	};
+
+	pic32_pinctrl: pinctrl@1f801400{
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "microchip,pic32mzda-pinctrl";
+		reg = <0x1f801400 0x400>;
+		clocks = <&PBCLK1>;
+	};
+
+	/* PORTA */
+	gpio0: gpio0@1f860000 {
+		compatible = "microchip,pic32mzda-gpio";
+		reg = <0x1f860000 0x100>;
+		interrupts = <118 IRQ_TYPE_LEVEL_HIGH>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		clocks = <&PBCLK4>;
+		microchip,gpio-bank = <0>;
+		gpio-ranges = <&pic32_pinctrl 0 0 16>;
+	};
+
+	/* PORTB */
+	gpio1: gpio1@1f860100 {
+		compatible = "microchip,pic32mzda-gpio";
+		reg = <0x1f860100 0x100>;
+		interrupts = <119 IRQ_TYPE_LEVEL_HIGH>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		clocks = <&PBCLK4>;
+		microchip,gpio-bank = <1>;
+		gpio-ranges = <&pic32_pinctrl 0 16 16>;
+	};
+
+	/* PORTC */
+	gpio2: gpio2@1f860200 {
+		compatible = "microchip,pic32mzda-gpio";
+		reg = <0x1f860200 0x100>;
+		interrupts = <120 IRQ_TYPE_LEVEL_HIGH>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		clocks = <&PBCLK4>;
+		microchip,gpio-bank = <2>;
+		gpio-ranges = <&pic32_pinctrl 0 32 16>;
+	};
+
+	/* PORTD */
+	gpio3: gpio3@1f860300 {
+		compatible = "microchip,pic32mzda-gpio";
+		reg = <0x1f860300 0x100>;
+		interrupts = <121 IRQ_TYPE_LEVEL_HIGH>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		clocks = <&PBCLK4>;
+		microchip,gpio-bank = <3>;
+		gpio-ranges = <&pic32_pinctrl 0 48 16>;
+	};
+
+	/* PORTE */
+	gpio4: gpio4@1f860400 {
+		compatible = "microchip,pic32mzda-gpio";
+		reg = <0x1f860400 0x100>;
+		interrupts = <122 IRQ_TYPE_LEVEL_HIGH>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		clocks = <&PBCLK4>;
+		microchip,gpio-bank = <4>;
+		gpio-ranges = <&pic32_pinctrl 0 64 16>;
+	};
+
+	/* PORTF */
+	gpio5: gpio5@1f860500 {
+		compatible = "microchip,pic32mzda-gpio";
+		reg = <0x1f860500 0x100>;
+		interrupts = <123 IRQ_TYPE_LEVEL_HIGH>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		clocks = <&PBCLK4>;
+		microchip,gpio-bank = <5>;
+		gpio-ranges = <&pic32_pinctrl 0 80 16>;
+	};
+
+	/* PORTG */
+	gpio6: gpio6@1f860600 {
+		compatible = "microchip,pic32mzda-gpio";
+		reg = <0x1f860600 0x100>;
+		interrupts = <124 IRQ_TYPE_LEVEL_HIGH>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		clocks = <&PBCLK4>;
+		microchip,gpio-bank = <6>;
+		gpio-ranges = <&pic32_pinctrl 0 96 16>;
+	};
+
+	/* PORTH */
+	gpio7: gpio7@1f860700 {
+		compatible = "microchip,pic32mzda-gpio";
+		reg = <0x1f860700 0x100>;
+		interrupts = <125 IRQ_TYPE_LEVEL_HIGH>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		clocks = <&PBCLK4>;
+		microchip,gpio-bank = <7>;
+		gpio-ranges = <&pic32_pinctrl 0 112 16>;
+	};
+
+	/* PORTI does not exist */
+
+	/* PORTJ */
+	gpio8: gpio8@1f860800 {
+		compatible = "microchip,pic32mzda-gpio";
+		reg = <0x1f860800 0x100>;
+		interrupts = <126 IRQ_TYPE_LEVEL_HIGH>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		clocks = <&PBCLK4>;
+		microchip,gpio-bank = <8>;
+		gpio-ranges = <&pic32_pinctrl 0 128 16>;
+	};
+
+	/* PORTK */
+	gpio9: gpio9@1f860900 {
+		compatible = "microchip,pic32mzda-gpio";
+		reg = <0x1f860900 0x100>;
+		interrupts = <127 IRQ_TYPE_LEVEL_HIGH>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		clocks = <&PBCLK4>;
+		microchip,gpio-bank = <9>;
+		gpio-ranges = <&pic32_pinctrl 0 144 16>;
+	};
+
+	sdhci: sdhci@1f8ec000 {
+		compatible = "microchip,pic32mzda-sdhci";
+		reg = <0x1f8ec000 0x100>;
+		interrupts = <191 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&REFCLKO4>, <&PBCLK5>;
+		clock-names = "base_clk", "sys_clk";
+		bus-width = <4>;
+		cap-sd-highspeed;
+		status = "disabled";
+	};
+
+	uart1: serial@1f822000 {
+		compatible = "microchip,pic32mzda-uart";
+		reg = <0x1f822000 0x50>;
+		interrupts = <112 IRQ_TYPE_LEVEL_HIGH>,
+			<113 IRQ_TYPE_LEVEL_HIGH>,
+			<114 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&PBCLK2>;
+		status = "disabled";
+	};
+
+	uart2: serial@1f822200 {
+		compatible = "microchip,pic32mzda-uart";
+		reg = <0x1f822200 0x50>;
+		interrupts = <145 IRQ_TYPE_LEVEL_HIGH>,
+			<146 IRQ_TYPE_LEVEL_HIGH>,
+			<147 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&PBCLK2>;
+		status = "disabled";
+	};
+
+	uart3: serial@1f822400 {
+		compatible = "microchip,pic32mzda-uart";
+		reg = <0x1f822400 0x50>;
+		interrupts = <157 IRQ_TYPE_LEVEL_HIGH>,
+			<158 IRQ_TYPE_LEVEL_HIGH>,
+			<159 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&PBCLK2>;
+		status = "disabled";
+	};
+
+	uart4: serial@1f822600 {
+		compatible = "microchip,pic32mzda-uart";
+		reg = <0x1f822600 0x50>;
+		interrupts = <170 IRQ_TYPE_LEVEL_HIGH>,
+			<171 IRQ_TYPE_LEVEL_HIGH>,
+			<172 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&PBCLK2>;
+		status = "disabled";
+	};
+
+	uart5: serial@1f822800 {
+		compatible = "microchip,pic32mzda-uart";
+		reg = <0x1f822800 0x50>;
+		interrupts = <179 IRQ_TYPE_LEVEL_HIGH>,
+			<180 IRQ_TYPE_LEVEL_HIGH>,
+			<181 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&PBCLK2>;
+		status = "disabled";
+	};
+
+	uart6: serial@1f822A00 {
+		compatible = "microchip,pic32mzda-uart";
+		reg = <0x1f822A00 0x50>;
+		interrupts = <188 IRQ_TYPE_LEVEL_HIGH>,
+			<189 IRQ_TYPE_LEVEL_HIGH>,
+			<190 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&PBCLK2>;
+		status = "disabled";
+	};
+};
diff --git a/arch/mips/boot/dts/pic32/pic32mzda_sk.dts b/arch/mips/boot/dts/pic32/pic32mzda_sk.dts
new file mode 100644
index 0000000..3fd2307
--- /dev/null
+++ b/arch/mips/boot/dts/pic32/pic32mzda_sk.dts
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2015 Microchip Technology Inc.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#include "pic32mzda.dtsi"
+
+/ {
+	compatible = "microchip,pic32mzda-sk", "microchip,pic32mzda";
+	model = "Microchip PIC32MZDA Starter Kit";
+
+	memory {
+		device_type = "memory";
+		reg = <0x08000000 0x08000000>;
+	};
+
+	chosen {
+		bootargs = "earlyprintk=ttyS1,115200n8r console=ttyS1,115200n8";
+	};
+
+	leds0 {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&user_leds_s0>;
+
+		led@1 {
+			label = "pic32mzda_sk:red:led1";
+			gpios = <&gpio7 0 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+
+		led@2 {
+			label = "pic32mzda_sk:yellow:led2";
+			gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc0";
+		};
+
+		led@3 {
+			label = "pic32mzda_sk:green:led3";
+			gpios = <&gpio7 2 GPIO_ACTIVE_HIGH>;
+			default-state = "on";
+		};
+	};
+
+	keys0 {
+		compatible = "gpio-keys";
+		pinctrl-0 = <&user_buttons_s0>;
+		pinctrl-names = "default";
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		button@sw1 {
+			label = "ESC";
+			linux,code = <1>;
+			gpios = <&gpio1 12 0>;
+		};
+
+		button@sw2 {
+			label = "Home";
+			linux,code = <102>;
+			gpios = <&gpio1 13 0>;
+		};
+
+		button@sw3 {
+			label = "Menu";
+			linux,code = <139>;
+			gpios = <&gpio1 14 0>;
+		};
+	};
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4>;
+	status = "okay";
+};
+
+&sdhci {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdhc1>;
+	status = "okay";
+	assigned-clocks = <&REFCLKO2>,<&REFCLKO4>,<&REFCLKO5>;
+	assigned-clock-rates = <50000000>,<25000000>,<40000000>;
+};
+
+&pic32_pinctrl {
+
+	pinctrl_sdhc1: sdhc1_pins0 {
+		pins = "A6", "D4", "G13", "G12", "G14", "A7", "A0";
+		microchip,digital;
+	};
+
+	user_leds_s0: user_leds_s0 {
+		pins = "H0", "H1", "H2";
+		output-low;
+		microchip,digital;
+	};
+
+	user_buttons_s0: user_buttons_s0 {
+		pins = "B12", "B13", "B14";
+		microchip,digital;
+		input-enable;
+		bias-pull-up;
+	};
+
+	pinctrl_uart2: pinctrl_uart2 {
+		uart2-tx {
+			pins = "G9";
+			function = "U2TX";
+			microchip,digital;
+			output-low;
+		};
+		uart2-rx {
+			pins = "B0";
+			function = "U2RX";
+			microchip,digital;
+			input-enable;
+		};
+	};
+
+	pinctrl_uart4: uart4-0 {
+		uart4-tx {
+			pins = "C3";
+			function = "U4TX";
+			microchip,digital;
+			output-low;
+		};
+		uart4-rx {
+			pins = "E8";
+			function = "U4RX";
+			microchip,digital;
+			input-enable;
+		};
+	};
+};
diff --git a/arch/mips/pic32/Kconfig b/arch/mips/pic32/Kconfig
index 0161f09..b1bd7ba 100644
--- a/arch/mips/pic32/Kconfig
+++ b/arch/mips/pic32/Kconfig
@@ -31,4 +31,20 @@ config PIC32MZDA
 
 endchoice
 
+choice
+	prompt "Devicetree selection"
+	default DTB_PIC32_NONE
+	help
+	  Select the devicetree.
+
+config DTB_PIC32_NONE
+       bool "None"
+
+config DTB_PIC32_MZDA_SK
+       bool "PIC32MZDA Starter Kit"
+       depends on PIC32MZDA
+       select BUILTIN_DTB
+
+endchoice
+
 endif # MACH_PIC32
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1291658 — [PATCH v2 09/14] DEVICETREE: Add bindings for PIC32 UART driver

FromJoshua Henderson <joshua.henderson@microchip.com>
Date2015-12-14 23:50 +0100
Subject[PATCH v2 09/14] DEVICETREE: Add bindings for PIC32 UART driver
Message-ID<qFK6m-3W4-31@gated-at.bofh.it>
In reply to#1291644
From: Andrei Pistirica <andrei.pistirica@microchip.com>

Document the devicetree bindings for the UART peripheral found on
Microchip PIC32 class devices.

Signed-off-by: Andrei Pistirica <andrei.pistirica@microchip.com>
Signed-off-by: Joshua Henderson <joshua.henderson@microchip.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
---
 .../bindings/serial/microchip,pic32-uart.txt       |   29 ++++++++++++++++++++
 1 file changed, 29 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt

diff --git a/Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt b/Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt
new file mode 100644
index 0000000..65b38bf6
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt
@@ -0,0 +1,29 @@
+* Microchip Universal Asynchronous Receiver Transmitter (UART)
+
+Required properties:
+- compatible: Should be "microchip,pic32mzda-uart"
+- reg: Should contain registers location and length
+- interrupts: Should contain interrupt
+- clocks: Phandle to the clock.
+          See: Documentation/devicetree/bindings/clock/clock-bindings.txt
+- pinctrl-names: A pinctrl state names "default" must be defined.
+- pinctrl-0: Phandle referencing pin configuration of the UART peripheral.
+             See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+
+Optional properties:
+- cts-gpios: CTS pin for UART
+
+Example:
+	uart1: serial@1f822000 {
+		compatible = "microchip,pic32mzda-uart";
+		reg = <0x1f822000 0x50>;
+		interrupts = <112 IRQ_TYPE_LEVEL_HIGH>,
+			<113 IRQ_TYPE_LEVEL_HIGH>,
+			<114 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&PBCLK2>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_uart1
+				&pinctrl_uart1_cts
+				&pinctrl_uart1_rts>;
+		cts-gpios = <&gpio1 15 0>;
+	};
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1292508 — Re: [PATCH v2 09/14] DEVICETREE: Add bindings for PIC32 UART driver

FromRob Herring <robh@kernel.org>
Date2015-12-15 21:10 +0100
SubjectRe: [PATCH v2 09/14] DEVICETREE: Add bindings for PIC32 UART driver
Message-ID<qG453-tz-9@gated-at.bofh.it>
In reply to#1291658
On Mon, Dec 14, 2015 at 03:42:11PM -0700, Joshua Henderson wrote:
> From: Andrei Pistirica <andrei.pistirica@microchip.com>
> 
> Document the devicetree bindings for the UART peripheral found on
> Microchip PIC32 class devices.
> 
> Signed-off-by: Andrei Pistirica <andrei.pistirica@microchip.com>
> Signed-off-by: Joshua Henderson <joshua.henderson@microchip.com>
> Cc: Ralf Baechle <ralf@linux-mips.org>

Acked-by: Rob Herring <robh@kernel.org>

> ---
>  .../bindings/serial/microchip,pic32-uart.txt       |   29 ++++++++++++++++++++
>  1 file changed, 29 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt
> 
> diff --git a/Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt b/Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt
> new file mode 100644
> index 0000000..65b38bf6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt
> @@ -0,0 +1,29 @@
> +* Microchip Universal Asynchronous Receiver Transmitter (UART)
> +
> +Required properties:
> +- compatible: Should be "microchip,pic32mzda-uart"
> +- reg: Should contain registers location and length
> +- interrupts: Should contain interrupt
> +- clocks: Phandle to the clock.
> +          See: Documentation/devicetree/bindings/clock/clock-bindings.txt
> +- pinctrl-names: A pinctrl state names "default" must be defined.
> +- pinctrl-0: Phandle referencing pin configuration of the UART peripheral.
> +             See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
> +
> +Optional properties:
> +- cts-gpios: CTS pin for UART
> +
> +Example:
> +	uart1: serial@1f822000 {
> +		compatible = "microchip,pic32mzda-uart";
> +		reg = <0x1f822000 0x50>;
> +		interrupts = <112 IRQ_TYPE_LEVEL_HIGH>,
> +			<113 IRQ_TYPE_LEVEL_HIGH>,
> +			<114 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&PBCLK2>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&pinctrl_uart1
> +				&pinctrl_uart1_cts
> +				&pinctrl_uart1_rts>;
> +		cts-gpios = <&gpio1 15 0>;
> +	};
> -- 
> 1.7.9.5
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1291659 — [PATCH v2 11/14] DEVICETREE: Add bindings for PIC32 SDHCI host controller

FromJoshua Henderson <joshua.henderson@microchip.com>
Date2015-12-14 23:50 +0100
Subject[PATCH v2 11/14] DEVICETREE: Add bindings for PIC32 SDHCI host controller
Message-ID<qFK6n-3W4-37@gated-at.bofh.it>
In reply to#1291644
From: Andrei Pistirica <andrei.pistirica@microchip.com>

Document the devicetree bindings for the SDHCI peripheral found on
Microchip PIC32 class devices.

Signed-off-by: Andrei Pistirica <andrei.pistirica@microchip.com>
Signed-off-by: Joshua Henderson <joshua.henderson@microchip.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
---
 .../bindings/mmc/microchip,sdhci-pic32.txt         |   29 ++++++++++++++++++++
 1 file changed, 29 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/microchip,sdhci-pic32.txt

diff --git a/Documentation/devicetree/bindings/mmc/microchip,sdhci-pic32.txt b/Documentation/devicetree/bindings/mmc/microchip,sdhci-pic32.txt
new file mode 100644
index 0000000..71ad57e
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/microchip,sdhci-pic32.txt
@@ -0,0 +1,29 @@
+* Microchip PIC32 SDHCI Controller
+
+This file documents differences between the core properties in mmc.txt
+and the properties used by the sdhci-pic32 driver.
+
+Required properties:
+- compatible: Should be "microchip,pic32mzda-sdhci"
+- interrupts: Should contain interrupt
+- clock-names: Should be "base_clk", "sys_clk".
+               See: Documentation/devicetree/bindings/resource-names.txt
+- clocks: Phandle to the clock.
+          See: Documentation/devicetree/bindings/clock/clock-bindings.txt
+- pinctrl-names: A pinctrl state names "default" must be defined.
+- pinctrl-0: Phandle referencing pin configuration of the SDHCI controller.
+             See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+
+Example:
+
+	sdhci@1f8ec000 {
+		compatible = "microchip,pic32mzda-sdhci";
+		reg = <0x1f8ec000 0x100>;
+		interrupts = <191 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&REFCLKO4>, <&PBCLK5>;
+		clock-names = "base_clk", "sys_clk";
+		bus-width = <4>;
+		cap-sd-highspeed;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_sdhc1>;
+	};
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1292513 — Re: [PATCH v2 11/14] DEVICETREE: Add bindings for PIC32 SDHCI host controller

FromRob Herring <robh@kernel.org>
Date2015-12-15 21:10 +0100
SubjectRe: [PATCH v2 11/14] DEVICETREE: Add bindings for PIC32 SDHCI host controller
Message-ID<qG453-tz-17@gated-at.bofh.it>
In reply to#1291659
On Mon, Dec 14, 2015 at 03:42:13PM -0700, Joshua Henderson wrote:
> From: Andrei Pistirica <andrei.pistirica@microchip.com>
> 
> Document the devicetree bindings for the SDHCI peripheral found on
> Microchip PIC32 class devices.
> 
> Signed-off-by: Andrei Pistirica <andrei.pistirica@microchip.com>
> Signed-off-by: Joshua Henderson <joshua.henderson@microchip.com>
> Cc: Ralf Baechle <ralf@linux-mips.org>

Acked-by: Rob Herring <robh@kernel.org>

> ---
>  .../bindings/mmc/microchip,sdhci-pic32.txt         |   29 ++++++++++++++++++++
>  1 file changed, 29 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mmc/microchip,sdhci-pic32.txt
> 
> diff --git a/Documentation/devicetree/bindings/mmc/microchip,sdhci-pic32.txt b/Documentation/devicetree/bindings/mmc/microchip,sdhci-pic32.txt
> new file mode 100644
> index 0000000..71ad57e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/microchip,sdhci-pic32.txt
> @@ -0,0 +1,29 @@
> +* Microchip PIC32 SDHCI Controller
> +
> +This file documents differences between the core properties in mmc.txt
> +and the properties used by the sdhci-pic32 driver.
> +
> +Required properties:
> +- compatible: Should be "microchip,pic32mzda-sdhci"
> +- interrupts: Should contain interrupt
> +- clock-names: Should be "base_clk", "sys_clk".
> +               See: Documentation/devicetree/bindings/resource-names.txt
> +- clocks: Phandle to the clock.
> +          See: Documentation/devicetree/bindings/clock/clock-bindings.txt
> +- pinctrl-names: A pinctrl state names "default" must be defined.
> +- pinctrl-0: Phandle referencing pin configuration of the SDHCI controller.
> +             See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
> +
> +Example:
> +
> +	sdhci@1f8ec000 {
> +		compatible = "microchip,pic32mzda-sdhci";
> +		reg = <0x1f8ec000 0x100>;
> +		interrupts = <191 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&REFCLKO4>, <&PBCLK5>;
> +		clock-names = "base_clk", "sys_clk";
> +		bus-width = <4>;
> +		cap-sd-highspeed;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&pinctrl_sdhc1>;
> +	};
> -- 
> 1.7.9.5
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1291661 — [PATCH v2 12/14] mmc: sdhci-pic32: Add PIC32 SDHCI host controller driver

FromJoshua Henderson <joshua.henderson@microchip.com>
Date2015-12-14 23:50 +0100
Subject[PATCH v2 12/14] mmc: sdhci-pic32: Add PIC32 SDHCI host controller driver
Message-ID<qFK6n-3W4-41@gated-at.bofh.it>
In reply to#1291644
From: Andrei Pistirica <andrei.pistirica@microchip.com>

This driver supports the SDHCI host controller found on a PIC32.

Signed-off-by: Andrei Pistirica <andrei.pistirica@microchip.com>
Signed-off-by: Joshua Henderson <joshua.henderson@microchip.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
---
 drivers/mmc/host/Kconfig       |   11 ++
 drivers/mmc/host/Makefile      |    1 +
 drivers/mmc/host/sdhci-pic32.c |  291 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 303 insertions(+)
 create mode 100644 drivers/mmc/host/sdhci-pic32.c

diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 1dee533..1a3a42b 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -785,3 +785,14 @@ config MMC_MTK
 	  If you have a machine with a integrated SD/MMC card reader, say Y or M here.
 	  This is needed if support for any SD/SDIO/MMC devices is required.
 	  If unsure, say N.
+
+config MMC_SDHCI_MICROCHIP_PIC32
+        tristate "Microchip PIC32MZDA SDHCI support"
+        depends on MMC_SDHCI && PIC32MZDA
+        help
+          This selects the Secure Digital Host Controller Interface (SDHCI)
+          for PIC32MZDA platform.
+
+          If you have a controller with this interface, say Y or M here.
+
+          If unsure, say N.
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 3595f83..af918d2 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -75,6 +75,7 @@ obj-$(CONFIG_MMC_SDHCI_BCM2835)		+= sdhci-bcm2835.o
 obj-$(CONFIG_MMC_SDHCI_IPROC)		+= sdhci-iproc.o
 obj-$(CONFIG_MMC_SDHCI_MSM)		+= sdhci-msm.o
 obj-$(CONFIG_MMC_SDHCI_ST)		+= sdhci-st.o
+obj-$(CONFIG_MMC_SDHCI_MICROCHIP_PIC32)	+= sdhci-pic32.o
 
 ifeq ($(CONFIG_CB710_DEBUG),y)
 	CFLAGS-cb710-mmc	+= -DDEBUG
diff --git a/drivers/mmc/host/sdhci-pic32.c b/drivers/mmc/host/sdhci-pic32.c
new file mode 100644
index 0000000..b7d7da2
--- /dev/null
+++ b/drivers/mmc/host/sdhci-pic32.c
@@ -0,0 +1,291 @@
+/*
+ * Support of SDHCI platform devices for Microchip PIC32.
+ *
+ * Copyright (C) 2015 Microchip
+ * Andrei Pistirica, Paul Thacker
+ *
+ * Inspired by sdhci-pltfm.c
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/highmem.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/mmc/host.h>
+#include <linux/io.h>
+#include "sdhci.h"
+#include <linux/platform_data/sdhci-pic32.h>
+
+#define SDH_SHARED_BUS_CTRL		0x000000E0
+#define SDH_SHARED_BUS_NR_CLK_PINS_MASK	0x7
+#define SDH_SHARED_BUS_NR_IRQ_PINS_MASK	0x30
+#define SDH_SHARED_BUS_CLK_PINS		0x10
+#define SDH_SHARED_BUS_IRQ_PINS		0x14
+#define SDH_CAPS_SDH_SLOT_TYPE_MASK	0xC0000000
+#define SDH_SLOT_TYPE_REMOVABLE		0x0
+#define SDH_SLOT_TYPE_EMBEDDED		0x1
+#define SDH_SLOT_TYPE_SHARED_BUS	0x2
+#define SDHCI_CTRL_CDSSEL		0x80
+#define SDHCI_CTRL_CDTLVL		0x40
+
+#define ADMA_FIFO_RD_THSHLD	512
+#define ADMA_FIFO_WR_THSHLD	512
+
+#define DEV_NAME "pic32-sdhci"
+
+struct pic32_sdhci_pdata {
+	struct platform_device	*pdev;
+	struct clk *sys_clk;
+	struct clk *base_clk;
+};
+
+static unsigned int pic32_sdhci_get_max_clock(struct sdhci_host *host)
+{
+	struct pic32_sdhci_pdata *sdhci_pdata = sdhci_priv(host);
+
+	return clk_get_rate(sdhci_pdata->base_clk);
+}
+
+static void pic32_sdhci_set_bus_width(struct sdhci_host *host, int width)
+{
+	u8 ctrl;
+
+	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
+	if (width == MMC_BUS_WIDTH_8) {
+		ctrl &= ~SDHCI_CTRL_4BITBUS;
+		if (host->version >= SDHCI_SPEC_300)
+			ctrl |= SDHCI_CTRL_8BITBUS;
+	} else {
+		if (host->version >= SDHCI_SPEC_300)
+			ctrl &= ~SDHCI_CTRL_8BITBUS;
+		if (width == MMC_BUS_WIDTH_4)
+			ctrl |= SDHCI_CTRL_4BITBUS;
+		else
+			ctrl &= ~SDHCI_CTRL_4BITBUS;
+	}
+	/*
+	 * SDHCI will not work if JTAG is not Connected.As a workaround fix,
+	 * set Card Detect Signal Selection bit in SDHCI Host Control
+	 * register and clear Card Detect Test Level bit in SDHCI Host
+	 * Control register.
+	 */
+	ctrl &= ~SDHCI_CTRL_CDTLVL;
+	ctrl |= SDHCI_CTRL_CDSSEL;
+	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+}
+
+static unsigned int pic32_sdhci_get_ro(struct sdhci_host *host)
+{
+	/*
+	 * The SDHCI_WRITE_PROTECT bit is unstable on current hardware so we
+	 * can't depend on its value in any way.
+	 */
+	return 0;
+}
+
+static const struct sdhci_ops pic32_sdhci_ops = {
+	.get_max_clock = pic32_sdhci_get_max_clock,
+	.set_clock = sdhci_set_clock,
+	.set_bus_width = pic32_sdhci_set_bus_width,
+	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
+	.get_ro = pic32_sdhci_get_ro,
+};
+
+static void pic32_sdhci_shared_bus(struct platform_device *pdev)
+{
+	struct sdhci_host *host = platform_get_drvdata(pdev);
+	u32 bus = readl(host->ioaddr + SDH_SHARED_BUS_CTRL);
+	u32 clk_pins = (bus & SDH_SHARED_BUS_NR_CLK_PINS_MASK) >> 0;
+	u32 irq_pins = (bus & SDH_SHARED_BUS_NR_IRQ_PINS_MASK) >> 4;
+
+	/* select first clock */
+	if (clk_pins & 0x1)
+		bus |= (0x1 << SDH_SHARED_BUS_CLK_PINS);
+
+	/* select first interrupt */
+	if (irq_pins & 0x1)
+		bus |= (0x1 << SDH_SHARED_BUS_IRQ_PINS);
+
+	writel(bus, host->ioaddr + SDH_SHARED_BUS_CTRL);
+}
+
+static int pic32_sdhci_probe_platform(struct platform_device *pdev,
+				      struct pic32_sdhci_pdata *pdata)
+{
+	int ret = 0;
+	u32 caps_slot_type;
+	struct sdhci_host *host = platform_get_drvdata(pdev);
+
+	/* Check card slot connected on shared bus. */
+	host->caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
+	caps_slot_type = (host->caps & SDH_CAPS_SDH_SLOT_TYPE_MASK) >> 30;
+	if (caps_slot_type == SDH_SLOT_TYPE_SHARED_BUS)
+		pic32_sdhci_shared_bus(pdev);
+
+	return ret;
+}
+
+static int pic32_sdhci_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct sdhci_host *host;
+	struct resource *iomem;
+	struct pic32_sdhci_pdata *sdhci_pdata;
+	struct pic32_sdhci_platform_data *plat_data;
+	unsigned int clk_rate = 0;
+	int ret;
+	struct pinctrl *pinctrl;
+
+	host = sdhci_alloc_host(dev, sizeof(*sdhci_pdata));
+	if (IS_ERR(host)) {
+		ret = PTR_ERR(host);
+		dev_err(&pdev->dev, "cannot allocate memory for sdhci\n");
+		goto err;
+	}
+
+	sdhci_pdata = sdhci_priv(host);
+	sdhci_pdata->pdev = pdev;
+	platform_set_drvdata(pdev, host);
+
+	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	host->ioaddr = devm_ioremap_resource(&pdev->dev, iomem);
+	if (IS_ERR(host->ioaddr)) {
+		ret = PTR_ERR(host->ioaddr);
+		dev_err(&pdev->dev, "unable to map iomem: %d\n", ret);
+		goto err_host;
+	}
+
+	plat_data = pdev->dev.platform_data;
+	if (plat_data && plat_data->setup_dma) {
+		ret = plat_data->setup_dma(ADMA_FIFO_RD_THSHLD,
+					   ADMA_FIFO_WR_THSHLD);
+		if (ret)
+			goto err_host;
+	}
+
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl)) {
+		ret = PTR_ERR(pinctrl);
+		dev_warn(&pdev->dev, "No pinctrl provided %d\n", ret);
+		if (ret == -EPROBE_DEFER)
+			goto err_host;
+	}
+
+	host->ops = &pic32_sdhci_ops;
+	host->irq = platform_get_irq(pdev, 0);
+
+	sdhci_pdata->sys_clk = devm_clk_get(&pdev->dev, "sys_clk");
+	if (IS_ERR(sdhci_pdata->sys_clk)) {
+		ret = PTR_ERR(sdhci_pdata->sys_clk);
+		dev_err(&pdev->dev, "Error getting clock\n");
+		goto err_host;
+	}
+
+	/* Enable clock when available! */
+	ret = clk_prepare_enable(sdhci_pdata->sys_clk);
+	if (ret) {
+		dev_dbg(&pdev->dev, "Error enabling clock\n");
+		goto err_host;
+	}
+
+	/* SDH CLK enable */
+	sdhci_pdata->base_clk = devm_clk_get(&pdev->dev, "base_clk");
+	if (IS_ERR(sdhci_pdata->base_clk)) {
+		ret = PTR_ERR(sdhci_pdata->base_clk);
+		dev_err(&pdev->dev, "Error getting clock\n");
+		goto err_host;
+	}
+
+	/* Enable clock when available! */
+	ret = clk_prepare_enable(sdhci_pdata->base_clk);
+	if (ret) {
+		dev_dbg(&pdev->dev, "Error enabling clock\n");
+		goto err_host;
+	}
+
+	clk_rate = clk_get_rate(sdhci_pdata->base_clk);
+	dev_dbg(&pdev->dev, "base clock at: %u\n", clk_rate);
+	clk_rate = clk_get_rate(sdhci_pdata->sys_clk);
+	dev_dbg(&pdev->dev, "sys clock at: %u\n", clk_rate);
+
+	host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
+
+	host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
+
+	ret = mmc_of_parse(host->mmc);
+	if (ret)
+		goto err_host;
+
+	ret = pic32_sdhci_probe_platform(pdev, sdhci_pdata);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to probe platform!\n");
+		goto err_host;
+	}
+
+	ret = sdhci_add_host(host);
+	if (ret) {
+		dev_dbg(&pdev->dev, "error adding host\n");
+		goto err_host;
+	}
+
+	dev_info(&pdev->dev, "Successfully added sdhci host\n");
+	return 0;
+
+err_host:
+	sdhci_free_host(host);
+err:
+	dev_err(&pdev->dev, "pic32-sdhci probe failed: %d\n", ret);
+	return ret;
+}
+
+static int pic32_sdhci_remove(struct platform_device *pdev)
+{
+	struct sdhci_host *host = platform_get_drvdata(pdev);
+	struct pic32_sdhci_pdata *sdhci_pdata = sdhci_priv(host);
+	int dead = 0;
+	u32 scratch;
+
+	scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
+	if (scratch == (u32)-1)
+		dead = 1;
+
+	sdhci_remove_host(host, dead);
+	clk_disable_unprepare(sdhci_pdata->base_clk);
+	clk_disable_unprepare(sdhci_pdata->sys_clk);
+	sdhci_free_host(host);
+
+	return 0;
+}
+
+static const struct of_device_id pic32_sdhci_id_table[] = {
+	{ .compatible = "microchip,pic32mzda-sdhci" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, pic32_sdhci_id_table);
+
+static struct platform_driver pic32_sdhci_driver = {
+	.driver = {
+		.name	= DEV_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(pic32_sdhci_id_table),
+	},
+	.probe		= pic32_sdhci_probe,
+	.remove		= pic32_sdhci_remove,
+};
+
+module_platform_driver(pic32_sdhci_driver);
+
+MODULE_DESCRIPTION("Microchip PIC32 SDHCI driver");
+MODULE_AUTHOR("Pistirica Sorin Andrei & Sandeep Sheriker");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1291729 — Re: [PATCH v2 12/14] mmc: sdhci-pic32: Add PIC32 SDHCI host controller driver

FromAndy Green <andy.green@linaro.org>
Date2015-12-15 01:40 +0100
SubjectRe: [PATCH v2 12/14] mmc: sdhci-pic32: Add PIC32 SDHCI host controller driver
Message-ID<qFLON-56v-19@gated-at.bofh.it>
In reply to#1291661
Hi... looks good, just some small general comments.

On 15 December 2015 at 06:42, Joshua Henderson
<joshua.henderson@microchip.com> wrote:
> From: Andrei Pistirica <andrei.pistirica@microchip.com>
>
> This driver supports the SDHCI host controller found on a PIC32.
>
> Signed-off-by: Andrei Pistirica <andrei.pistirica@microchip.com>
> Signed-off-by: Joshua Henderson <joshua.henderson@microchip.com>
> Cc: Ralf Baechle <ralf@linux-mips.org>
> ---
>  drivers/mmc/host/Kconfig       |   11 ++
>  drivers/mmc/host/Makefile      |    1 +
>  drivers/mmc/host/sdhci-pic32.c |  291 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 303 insertions(+)
>  create mode 100644 drivers/mmc/host/sdhci-pic32.c
>
> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> index 1dee533..1a3a42b 100644
> --- a/drivers/mmc/host/Kconfig
> +++ b/drivers/mmc/host/Kconfig
> @@ -785,3 +785,14 @@ config MMC_MTK
>           If you have a machine with a integrated SD/MMC card reader, say Y or M here.
>           This is needed if support for any SD/SDIO/MMC devices is required.
>           If unsure, say N.
> +
> +config MMC_SDHCI_MICROCHIP_PIC32
> +        tristate "Microchip PIC32MZDA SDHCI support"
> +        depends on MMC_SDHCI && PIC32MZDA
> +        help
> +          This selects the Secure Digital Host Controller Interface (SDHCI)
> +          for PIC32MZDA platform.
> +
> +          If you have a controller with this interface, say Y or M here.
> +
> +          If unsure, say N.
> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
> index 3595f83..af918d2 100644
> --- a/drivers/mmc/host/Makefile
> +++ b/drivers/mmc/host/Makefile
> @@ -75,6 +75,7 @@ obj-$(CONFIG_MMC_SDHCI_BCM2835)               += sdhci-bcm2835.o
>  obj-$(CONFIG_MMC_SDHCI_IPROC)          += sdhci-iproc.o
>  obj-$(CONFIG_MMC_SDHCI_MSM)            += sdhci-msm.o
>  obj-$(CONFIG_MMC_SDHCI_ST)             += sdhci-st.o
> +obj-$(CONFIG_MMC_SDHCI_MICROCHIP_PIC32)        += sdhci-pic32.o
>
>  ifeq ($(CONFIG_CB710_DEBUG),y)
>         CFLAGS-cb710-mmc        += -DDEBUG
> diff --git a/drivers/mmc/host/sdhci-pic32.c b/drivers/mmc/host/sdhci-pic32.c
> new file mode 100644
> index 0000000..b7d7da2
> --- /dev/null
> +++ b/drivers/mmc/host/sdhci-pic32.c
> @@ -0,0 +1,291 @@
> +/*
> + * Support of SDHCI platform devices for Microchip PIC32.
> + *
> + * Copyright (C) 2015 Microchip
> + * Andrei Pistirica, Paul Thacker
> + *
> + * Inspired by sdhci-pltfm.c
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/highmem.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm.h>
> +#include <linux/slab.h>
> +#include <linux/mmc/host.h>
> +#include <linux/io.h>
> +#include "sdhci.h"
> +#include <linux/platform_data/sdhci-pic32.h>
> +
> +#define SDH_SHARED_BUS_CTRL            0x000000E0
> +#define SDH_SHARED_BUS_NR_CLK_PINS_MASK        0x7
> +#define SDH_SHARED_BUS_NR_IRQ_PINS_MASK        0x30
> +#define SDH_SHARED_BUS_CLK_PINS                0x10
> +#define SDH_SHARED_BUS_IRQ_PINS                0x14
> +#define SDH_CAPS_SDH_SLOT_TYPE_MASK    0xC0000000
> +#define SDH_SLOT_TYPE_REMOVABLE                0x0
> +#define SDH_SLOT_TYPE_EMBEDDED         0x1
> +#define SDH_SLOT_TYPE_SHARED_BUS       0x2
> +#define SDHCI_CTRL_CDSSEL              0x80
> +#define SDHCI_CTRL_CDTLVL              0x40
> +
> +#define ADMA_FIFO_RD_THSHLD    512
> +#define ADMA_FIFO_WR_THSHLD    512
> +
> +#define DEV_NAME "pic32-sdhci"

Is there any point defining this when it only has one use in the driver?

> +struct pic32_sdhci_pdata {
> +       struct platform_device  *pdev;
> +       struct clk *sys_clk;
> +       struct clk *base_clk;
> +};
> +
> +static unsigned int pic32_sdhci_get_max_clock(struct sdhci_host *host)
> +{
> +       struct pic32_sdhci_pdata *sdhci_pdata = sdhci_priv(host);
> +
> +       return clk_get_rate(sdhci_pdata->base_clk);
> +}
> +
> +static void pic32_sdhci_set_bus_width(struct sdhci_host *host, int width)
> +{
> +       u8 ctrl;
> +
> +       ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
> +       if (width == MMC_BUS_WIDTH_8) {
> +               ctrl &= ~SDHCI_CTRL_4BITBUS;
> +               if (host->version >= SDHCI_SPEC_300)
> +                       ctrl |= SDHCI_CTRL_8BITBUS;
> +       } else {
> +               if (host->version >= SDHCI_SPEC_300)
> +                       ctrl &= ~SDHCI_CTRL_8BITBUS;
> +               if (width == MMC_BUS_WIDTH_4)
> +                       ctrl |= SDHCI_CTRL_4BITBUS;
> +               else
> +                       ctrl &= ~SDHCI_CTRL_4BITBUS;
> +       }
> +       /*
> +        * SDHCI will not work if JTAG is not Connected.As a workaround fix,
> +        * set Card Detect Signal Selection bit in SDHCI Host Control
> +        * register and clear Card Detect Test Level bit in SDHCI Host
> +        * Control register.
> +        */

Isn't this a clearer explanation, if I understood?

"Without setting CD select and test bits now, SDHCI only works with
JTAG connected."

> +       ctrl &= ~SDHCI_CTRL_CDTLVL;
> +       ctrl |= SDHCI_CTRL_CDSSEL;
> +       sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);

Also... is that a feature of the SDHCI IP or this particular chip's
implementation of it?  I guess if there is only one implementation
right now that has that restriction worry about making it selectable
later.  But if the implementation, it might make sense to also put the
affected implementation name in the comment to make it clear.

> +}
> +
> +static unsigned int pic32_sdhci_get_ro(struct sdhci_host *host)
> +{
> +       /*
> +        * The SDHCI_WRITE_PROTECT bit is unstable on current hardware so we
> +        * can't depend on its value in any way.
> +        */
> +       return 0;
> +}
> +
> +static const struct sdhci_ops pic32_sdhci_ops = {
> +       .get_max_clock = pic32_sdhci_get_max_clock,
> +       .set_clock = sdhci_set_clock,
> +       .set_bus_width = pic32_sdhci_set_bus_width,
> +       .reset = sdhci_reset,
> +       .set_uhs_signaling = sdhci_set_uhs_signaling,
> +       .get_ro = pic32_sdhci_get_ro,
> +};
> +
> +static void pic32_sdhci_shared_bus(struct platform_device *pdev)
> +{
> +       struct sdhci_host *host = platform_get_drvdata(pdev);
> +       u32 bus = readl(host->ioaddr + SDH_SHARED_BUS_CTRL);
> +       u32 clk_pins = (bus & SDH_SHARED_BUS_NR_CLK_PINS_MASK) >> 0;
> +       u32 irq_pins = (bus & SDH_SHARED_BUS_NR_IRQ_PINS_MASK) >> 4;
> +
> +       /* select first clock */
> +       if (clk_pins & 0x1)

BIT(0)?  Also a couple of lines down.

> +               bus |= (0x1 << SDH_SHARED_BUS_CLK_PINS);

I know it's popular but there is no meaning or use in "0x1" where you
could just say "1".

> +       /* select first interrupt */
> +       if (irq_pins & 0x1)
> +               bus |= (0x1 << SDH_SHARED_BUS_IRQ_PINS);

As above.

> +       writel(bus, host->ioaddr + SDH_SHARED_BUS_CTRL);
> +}
> +
> +static int pic32_sdhci_probe_platform(struct platform_device *pdev,
> +                                     struct pic32_sdhci_pdata *pdata)
> +{
> +       int ret = 0;
> +       u32 caps_slot_type;
> +       struct sdhci_host *host = platform_get_drvdata(pdev);
> +
> +       /* Check card slot connected on shared bus. */
> +       host->caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
> +       caps_slot_type = (host->caps & SDH_CAPS_SDH_SLOT_TYPE_MASK) >> 30;
> +       if (caps_slot_type == SDH_SLOT_TYPE_SHARED_BUS)
> +               pic32_sdhci_shared_bus(pdev);
> +
> +       return ret;
> +}
> +
> +static int pic32_sdhci_probe(struct platform_device *pdev)
> +{
> +       struct device *dev = &pdev->dev;
> +       struct sdhci_host *host;
> +       struct resource *iomem;
> +       struct pic32_sdhci_pdata *sdhci_pdata;
> +       struct pic32_sdhci_platform_data *plat_data;
> +       unsigned int clk_rate = 0;
> +       int ret;
> +       struct pinctrl *pinctrl;

It's hardly critical but for extra gold star arranging local vars in
length order (longest first) is nice.

> +
> +       host = sdhci_alloc_host(dev, sizeof(*sdhci_pdata));
> +       if (IS_ERR(host)) {
> +               ret = PTR_ERR(host);
> +               dev_err(&pdev->dev, "cannot allocate memory for sdhci\n");
> +               goto err;
> +       }
> +
> +       sdhci_pdata = sdhci_priv(host);
> +       sdhci_pdata->pdev = pdev;
> +       platform_set_drvdata(pdev, host);
> +
> +       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       host->ioaddr = devm_ioremap_resource(&pdev->dev, iomem);
> +       if (IS_ERR(host->ioaddr)) {
> +               ret = PTR_ERR(host->ioaddr);
> +               dev_err(&pdev->dev, "unable to map iomem: %d\n", ret);
> +               goto err_host;
> +       }
> +
> +       plat_data = pdev->dev.platform_data;
> +       if (plat_data && plat_data->setup_dma) {
> +               ret = plat_data->setup_dma(ADMA_FIFO_RD_THSHLD,
> +                                          ADMA_FIFO_WR_THSHLD);
> +               if (ret)
> +                       goto err_host;
> +       }
> +
> +       pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
> +       if (IS_ERR(pinctrl)) {
> +               ret = PTR_ERR(pinctrl);
> +               dev_warn(&pdev->dev, "No pinctrl provided %d\n", ret);
> +               if (ret == -EPROBE_DEFER)
> +                       goto err_host;
> +       }
> +
> +       host->ops = &pic32_sdhci_ops;
> +       host->irq = platform_get_irq(pdev, 0);
> +
> +       sdhci_pdata->sys_clk = devm_clk_get(&pdev->dev, "sys_clk");
> +       if (IS_ERR(sdhci_pdata->sys_clk)) {
> +               ret = PTR_ERR(sdhci_pdata->sys_clk);
> +               dev_err(&pdev->dev, "Error getting clock\n");
> +               goto err_host;
> +       }
> +
> +       /* Enable clock when available! */
> +       ret = clk_prepare_enable(sdhci_pdata->sys_clk);
> +       if (ret) {
> +               dev_dbg(&pdev->dev, "Error enabling clock\n");

Shouldn't this be dev_err()?  You don't survive not having the clock
in the stanza above.  So if you have the clock, you would want to know
if it didn't deal with the clk_prepare_enable().

The comment 4 lines above is also wrong if so.

> +               goto err_host;
> +       }
> +
> +       /* SDH CLK enable */
> +       sdhci_pdata->base_clk = devm_clk_get(&pdev->dev, "base_clk");
> +       if (IS_ERR(sdhci_pdata->base_clk)) {
> +               ret = PTR_ERR(sdhci_pdata->base_clk);
> +               dev_err(&pdev->dev, "Error getting clock\n");
> +               goto err_host;
> +       }
> +
> +       /* Enable clock when available! */
> +       ret = clk_prepare_enable(sdhci_pdata->base_clk);

Again the comment seems wrong.

> +       if (ret) {
> +               dev_dbg(&pdev->dev, "Error enabling clock\n");

And if I understood it, dev_err() needed.

> +               goto err_host;
> +       }
> +
> +       clk_rate = clk_get_rate(sdhci_pdata->base_clk);
> +       dev_dbg(&pdev->dev, "base clock at: %u\n", clk_rate);
> +       clk_rate = clk_get_rate(sdhci_pdata->sys_clk);
> +       dev_dbg(&pdev->dev, "sys clock at: %u\n", clk_rate);
> +
> +       host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
> +

Probably can lose the blank line.

> +       host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
> +
> +       ret = mmc_of_parse(host->mmc);
> +       if (ret)
> +               goto err_host;
> +
> +       ret = pic32_sdhci_probe_platform(pdev, sdhci_pdata);
> +       if (ret) {
> +               dev_err(&pdev->dev, "failed to probe platform!\n");
> +               goto err_host;
> +       }
> +
> +       ret = sdhci_add_host(host);
> +       if (ret) {
> +               dev_dbg(&pdev->dev, "error adding host\n");
> +               goto err_host;
> +       }
> +
> +       dev_info(&pdev->dev, "Successfully added sdhci host\n");
> +       return 0;
> +
> +err_host:
> +       sdhci_free_host(host);
> +err:
> +       dev_err(&pdev->dev, "pic32-sdhci probe failed: %d\n", ret);
> +       return ret;
> +}
> +
> +static int pic32_sdhci_remove(struct platform_device *pdev)
> +{
> +       struct sdhci_host *host = platform_get_drvdata(pdev);
> +       struct pic32_sdhci_pdata *sdhci_pdata = sdhci_priv(host);
> +       int dead = 0;
> +       u32 scratch;
> +
> +       scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
> +       if (scratch == (u32)-1)

Since it's not actually related to signed, (u32)~0 might be clearer.

> +               dead = 1;
> +
> +       sdhci_remove_host(host, dead);

You could get rid of "dead" and have

         sdhci_remove_host(host, scratch == (u32)~0);

> +       clk_disable_unprepare(sdhci_pdata->base_clk);
> +       clk_disable_unprepare(sdhci_pdata->sys_clk);
> +       sdhci_free_host(host);
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id pic32_sdhci_id_table[] = {
> +       { .compatible = "microchip,pic32mzda-sdhci" },
> +       {}
> +};
> +MODULE_DEVICE_TABLE(of, pic32_sdhci_id_table);
> +
> +static struct platform_driver pic32_sdhci_driver = {
> +       .driver = {
> +               .name   = DEV_NAME,
> +               .owner  = THIS_MODULE,
> +               .of_match_table = of_match_ptr(pic32_sdhci_id_table),
> +       },
> +       .probe          = pic32_sdhci_probe,
> +       .remove         = pic32_sdhci_remove,
> +};
> +
> +module_platform_driver(pic32_sdhci_driver);
> +
> +MODULE_DESCRIPTION("Microchip PIC32 SDHCI driver");
> +MODULE_AUTHOR("Pistirica Sorin Andrei & Sandeep Sheriker");
> +MODULE_LICENSE("GPL v2");
> --
> 1.7.9.5
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1293146 — RE: [PATCH v2 12/14] mmc: sdhci-pic32: Add PIC32 SDHCI host controller driver

From<Paul.Thacker@microchip.com>
Date2015-12-16 18:40 +0100
SubjectRE: [PATCH v2 12/14] mmc: sdhci-pic32: Add PIC32 SDHCI host controller driver
Message-ID<qGods-4KL-9@gated-at.bofh.it>
In reply to#1291729
T24gMTIvMTQvMjAxNSA1OjMzIFBNLCBBbmR5IEdyZWVuIHdyb3RlOg0KPiBIaS4uLiBsb29rcyBn
b29kLCBqdXN0IHNvbWUgc21hbGwgZ2VuZXJhbCBjb21tZW50cy4NCj4gDQo+IE9uIDE1IERlY2Vt
YmVyIDIwMTUgYXQgMDY6NDIsIEpvc2h1YSBIZW5kZXJzb24NCj4gPGpvc2h1YS5oZW5kZXJzb25A
bWljcm9jaGlwLmNvbT4gd3JvdGU6DQo+ID4gRnJvbTogQW5kcmVpIFBpc3RpcmljYSA8YW5kcmVp
LnBpc3RpcmljYUBtaWNyb2NoaXAuY29tPg0KPiA+DQo+ID4gVGhpcyBkcml2ZXIgc3VwcG9ydHMg
dGhlIFNESENJIGhvc3QgY29udHJvbGxlciBmb3VuZCBvbiBhIFBJQzMyLg0KPiA+DQo+ID4gU2ln
bmVkLW9mZi1ieTogQW5kcmVpIFBpc3RpcmljYSA8YW5kcmVpLnBpc3RpcmljYUBtaWNyb2NoaXAu
Y29tPg0KPiA+IFNpZ25lZC1vZmYtYnk6IEpvc2h1YSBIZW5kZXJzb24gPGpvc2h1YS5oZW5kZXJz
b25AbWljcm9jaGlwLmNvbT4NCj4gPiBDYzogUmFsZiBCYWVjaGxlIDxyYWxmQGxpbnV4LW1pcHMu
b3JnPg0KPiA+IC0tLQ0KPiA+ICBkcml2ZXJzL21tYy9ob3N0L0tjb25maWcgICAgICAgfCAgIDEx
ICsrDQo+ID4gIGRyaXZlcnMvbW1jL2hvc3QvTWFrZWZpbGUgICAgICB8ICAgIDEgKw0KPiA+ICBk
cml2ZXJzL21tYy9ob3N0L3NkaGNpLXBpYzMyLmMgfCAgMjkxDQo+ID4gKysrKysrKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKysrKw0KPiA+ICAzIGZpbGVzIGNoYW5nZWQsIDMwMyBpbnNl
cnRpb25zKCspDQo+ID4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL21tYy9ob3N0L3NkaGNp
LXBpYzMyLmMNCj4gPg0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL21tYy9ob3N0L0tjb25maWcg
Yi9kcml2ZXJzL21tYy9ob3N0L0tjb25maWcgaW5kZXgNCj4gPiAxZGVlNTMzLi4xYTNhNDJiIDEw
MDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvbW1jL2hvc3QvS2NvbmZpZw0KPiA+ICsrKyBiL2RyaXZl
cnMvbW1jL2hvc3QvS2NvbmZpZw0KPiA+IEBAIC03ODUsMyArNzg1LDE0IEBAIGNvbmZpZyBNTUNf
TVRLDQo+ID4gICAgICAgICAgIElmIHlvdSBoYXZlIGEgbWFjaGluZSB3aXRoIGEgaW50ZWdyYXRl
ZCBTRC9NTUMgY2FyZCByZWFkZXIsIHNheSBZIG9yIE0NCj4gaGVyZS4NCj4gPiAgICAgICAgICAg
VGhpcyBpcyBuZWVkZWQgaWYgc3VwcG9ydCBmb3IgYW55IFNEL1NESU8vTU1DIGRldmljZXMgaXMg
cmVxdWlyZWQuDQo+ID4gICAgICAgICAgIElmIHVuc3VyZSwgc2F5IE4uDQo+ID4gKw0KPiA+ICtj
b25maWcgTU1DX1NESENJX01JQ1JPQ0hJUF9QSUMzMg0KPiA+ICsgICAgICAgIHRyaXN0YXRlICJN
aWNyb2NoaXAgUElDMzJNWkRBIFNESENJIHN1cHBvcnQiDQo+ID4gKyAgICAgICAgZGVwZW5kcyBv
biBNTUNfU0RIQ0kgJiYgUElDMzJNWkRBDQo+ID4gKyAgICAgICAgaGVscA0KPiA+ICsgICAgICAg
ICAgVGhpcyBzZWxlY3RzIHRoZSBTZWN1cmUgRGlnaXRhbCBIb3N0IENvbnRyb2xsZXIgSW50ZXJm
YWNlIChTREhDSSkNCj4gPiArICAgICAgICAgIGZvciBQSUMzMk1aREEgcGxhdGZvcm0uDQo+ID4g
Kw0KPiA+ICsgICAgICAgICAgSWYgeW91IGhhdmUgYSBjb250cm9sbGVyIHdpdGggdGhpcyBpbnRl
cmZhY2UsIHNheSBZIG9yIE0gaGVyZS4NCj4gPiArDQo+ID4gKyAgICAgICAgICBJZiB1bnN1cmUs
IHNheSBOLg0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL21tYy9ob3N0L01ha2VmaWxlIGIvZHJp
dmVycy9tbWMvaG9zdC9NYWtlZmlsZQ0KPiA+IGluZGV4IDM1OTVmODMuLmFmOTE4ZDIgMTAwNjQ0
DQo+ID4gLS0tIGEvZHJpdmVycy9tbWMvaG9zdC9NYWtlZmlsZQ0KPiA+ICsrKyBiL2RyaXZlcnMv
bW1jL2hvc3QvTWFrZWZpbGUNCj4gPiBAQCAtNzUsNiArNzUsNyBAQCBvYmotJChDT05GSUdfTU1D
X1NESENJX0JDTTI4MzUpICAgICAgICAgICAgICAgKz0gc2RoY2ktDQo+IGJjbTI4MzUubw0KPiA+
ICBvYmotJChDT05GSUdfTU1DX1NESENJX0lQUk9DKSAgICAgICAgICArPSBzZGhjaS1pcHJvYy5v
DQo+ID4gIG9iai0kKENPTkZJR19NTUNfU0RIQ0lfTVNNKSAgICAgICAgICAgICs9IHNkaGNpLW1z
bS5vDQo+ID4gIG9iai0kKENPTkZJR19NTUNfU0RIQ0lfU1QpICAgICAgICAgICAgICs9IHNkaGNp
LXN0Lm8NCj4gPiArb2JqLSQoQ09ORklHX01NQ19TREhDSV9NSUNST0NISVBfUElDMzIpICAgICAg
ICArPSBzZGhjaS1waWMzMi5vDQo+ID4NCj4gPiAgaWZlcSAoJChDT05GSUdfQ0I3MTBfREVCVUcp
LHkpDQo+ID4gICAgICAgICBDRkxBR1MtY2I3MTAtbW1jICAgICAgICArPSAtRERFQlVHDQo+ID4g
ZGlmZiAtLWdpdCBhL2RyaXZlcnMvbW1jL2hvc3Qvc2RoY2ktcGljMzIuYw0KPiA+IGIvZHJpdmVy
cy9tbWMvaG9zdC9zZGhjaS1waWMzMi5jIG5ldyBmaWxlIG1vZGUgMTAwNjQ0IGluZGV4DQo+ID4g
MDAwMDAwMC4uYjdkN2RhMg0KPiA+IC0tLSAvZGV2L251bGwNCj4gPiArKysgYi9kcml2ZXJzL21t
Yy9ob3N0L3NkaGNpLXBpYzMyLmMNCj4gPiBAQCAtMCwwICsxLDI5MSBAQA0KPiA+ICsvKg0KPiA+
ICsgKiBTdXBwb3J0IG9mIFNESENJIHBsYXRmb3JtIGRldmljZXMgZm9yIE1pY3JvY2hpcCBQSUMz
Mi4NCj4gPiArICoNCj4gPiArICogQ29weXJpZ2h0IChDKSAyMDE1IE1pY3JvY2hpcA0KPiA+ICsg
KiBBbmRyZWkgUGlzdGlyaWNhLCBQYXVsIFRoYWNrZXINCj4gPiArICoNCj4gPiArICogSW5zcGly
ZWQgYnkgc2RoY2ktcGx0Zm0uYw0KPiA+ICsgKg0KPiA+ICsgKiBUaGlzIGZpbGUgaXMgbGljZW5z
ZWQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMNCj4gPiArICogTGlj
ZW5zZSB2ZXJzaW9uIDIuIFRoaXMgcHJvZ3JhbSBpcyBsaWNlbnNlZCAiYXMgaXMiIHdpdGhvdXQg
YW55DQo+ID4gKyAqIHdhcnJhbnR5IG9mIGFueSBraW5kLCB3aGV0aGVyIGV4cHJlc3Mgb3IgaW1w
bGllZC4NCj4gPiArICovDQo+ID4gKw0KPiA+ICsjaW5jbHVkZSA8bGludXgvY2xrLmg+DQo+ID4g
KyNpbmNsdWRlIDxsaW51eC9kZWxheS5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvaGlnaG1lbS5o
Pg0KPiA+ICsjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9p
bnRlcnJ1cHQuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L2lycS5oPg0KPiA+ICsjaW5jbHVkZSA8
bGludXgvb2YuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L3BsYXRmb3JtX2RldmljZS5oPg0KPiA+
ICsjaW5jbHVkZSA8bGludXgvcG0uaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L3NsYWIuaD4NCj4g
PiArI2luY2x1ZGUgPGxpbnV4L21tYy9ob3N0Lmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9pby5o
Pg0KPiA+ICsjaW5jbHVkZSAic2RoY2kuaCINCj4gPiArI2luY2x1ZGUgPGxpbnV4L3BsYXRmb3Jt
X2RhdGEvc2RoY2ktcGljMzIuaD4NCj4gPiArDQo+ID4gKyNkZWZpbmUgU0RIX1NIQVJFRF9CVVNf
Q1RSTCAgICAgICAgICAgIDB4MDAwMDAwRTANCj4gPiArI2RlZmluZSBTREhfU0hBUkVEX0JVU19O
Ul9DTEtfUElOU19NQVNLICAgICAgICAweDcNCj4gPiArI2RlZmluZSBTREhfU0hBUkVEX0JVU19O
Ul9JUlFfUElOU19NQVNLICAgICAgICAweDMwDQo+ID4gKyNkZWZpbmUgU0RIX1NIQVJFRF9CVVNf
Q0xLX1BJTlMgICAgICAgICAgICAgICAgMHgxMA0KPiA+ICsjZGVmaW5lIFNESF9TSEFSRURfQlVT
X0lSUV9QSU5TICAgICAgICAgICAgICAgIDB4MTQNCj4gPiArI2RlZmluZSBTREhfQ0FQU19TREhf
U0xPVF9UWVBFX01BU0sgICAgMHhDMDAwMDAwMA0KPiA+ICsjZGVmaW5lIFNESF9TTE9UX1RZUEVf
UkVNT1ZBQkxFICAgICAgICAgICAgICAgIDB4MA0KPiA+ICsjZGVmaW5lIFNESF9TTE9UX1RZUEVf
RU1CRURERUQgICAgICAgICAweDENCj4gPiArI2RlZmluZSBTREhfU0xPVF9UWVBFX1NIQVJFRF9C
VVMgICAgICAgMHgyDQo+ID4gKyNkZWZpbmUgU0RIQ0lfQ1RSTF9DRFNTRUwgICAgICAgICAgICAg
IDB4ODANCj4gPiArI2RlZmluZSBTREhDSV9DVFJMX0NEVExWTCAgICAgICAgICAgICAgMHg0MA0K
PiA+ICsNCj4gPiArI2RlZmluZSBBRE1BX0ZJRk9fUkRfVEhTSExEICAgIDUxMg0KPiA+ICsjZGVm
aW5lIEFETUFfRklGT19XUl9USFNITEQgICAgNTEyDQo+ID4gKw0KPiA+ICsjZGVmaW5lIERFVl9O
QU1FICJwaWMzMi1zZGhjaSINCj4gDQo+IElzIHRoZXJlIGFueSBwb2ludCBkZWZpbmluZyB0aGlz
IHdoZW4gaXQgb25seSBoYXMgb25lIHVzZSBpbiB0aGUgZHJpdmVyPw0KDQpBY2suIFdpbGwgcmVt
b3ZlLg0KDQo+IA0KPiA+ICtzdHJ1Y3QgcGljMzJfc2RoY2lfcGRhdGEgew0KPiA+ICsgICAgICAg
c3RydWN0IHBsYXRmb3JtX2RldmljZSAgKnBkZXY7DQo+ID4gKyAgICAgICBzdHJ1Y3QgY2xrICpz
eXNfY2xrOw0KPiA+ICsgICAgICAgc3RydWN0IGNsayAqYmFzZV9jbGs7DQo+ID4gK307DQo+ID4g
Kw0KPiA+ICtzdGF0aWMgdW5zaWduZWQgaW50IHBpYzMyX3NkaGNpX2dldF9tYXhfY2xvY2soc3Ry
dWN0IHNkaGNpX2hvc3QNCj4gPiArKmhvc3QpIHsNCj4gPiArICAgICAgIHN0cnVjdCBwaWMzMl9z
ZGhjaV9wZGF0YSAqc2RoY2lfcGRhdGEgPSBzZGhjaV9wcml2KGhvc3QpOw0KPiA+ICsNCj4gPiAr
ICAgICAgIHJldHVybiBjbGtfZ2V0X3JhdGUoc2RoY2lfcGRhdGEtPmJhc2VfY2xrKTsNCj4gPiAr
fQ0KPiA+ICsNCj4gPiArc3RhdGljIHZvaWQgcGljMzJfc2RoY2lfc2V0X2J1c193aWR0aChzdHJ1
Y3Qgc2RoY2lfaG9zdCAqaG9zdCwgaW50DQo+ID4gK3dpZHRoKSB7DQo+ID4gKyAgICAgICB1OCBj
dHJsOw0KPiA+ICsNCj4gPiArICAgICAgIGN0cmwgPSBzZGhjaV9yZWFkYihob3N0LCBTREhDSV9I
T1NUX0NPTlRST0wpOw0KPiA+ICsgICAgICAgaWYgKHdpZHRoID09IE1NQ19CVVNfV0lEVEhfOCkg
ew0KPiA+ICsgICAgICAgICAgICAgICBjdHJsICY9IH5TREhDSV9DVFJMXzRCSVRCVVM7DQo+ID4g
KyAgICAgICAgICAgICAgIGlmIChob3N0LT52ZXJzaW9uID49IFNESENJX1NQRUNfMzAwKQ0KPiA+
ICsgICAgICAgICAgICAgICAgICAgICAgIGN0cmwgfD0gU0RIQ0lfQ1RSTF84QklUQlVTOw0KPiA+
ICsgICAgICAgfSBlbHNlIHsNCj4gPiArICAgICAgICAgICAgICAgaWYgKGhvc3QtPnZlcnNpb24g
Pj0gU0RIQ0lfU1BFQ18zMDApDQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgY3RybCAmPSB+
U0RIQ0lfQ1RSTF84QklUQlVTOw0KPiA+ICsgICAgICAgICAgICAgICBpZiAod2lkdGggPT0gTU1D
X0JVU19XSURUSF80KQ0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIGN0cmwgfD0gU0RIQ0lf
Q1RSTF80QklUQlVTOw0KPiA+ICsgICAgICAgICAgICAgICBlbHNlDQo+ID4gKyAgICAgICAgICAg
ICAgICAgICAgICAgY3RybCAmPSB+U0RIQ0lfQ1RSTF80QklUQlVTOw0KPiA+ICsgICAgICAgfQ0K
PiA+ICsgICAgICAgLyoNCj4gPiArICAgICAgICAqIFNESENJIHdpbGwgbm90IHdvcmsgaWYgSlRB
RyBpcyBub3QgQ29ubmVjdGVkLkFzIGEgd29ya2Fyb3VuZCBmaXgsDQo+ID4gKyAgICAgICAgKiBz
ZXQgQ2FyZCBEZXRlY3QgU2lnbmFsIFNlbGVjdGlvbiBiaXQgaW4gU0RIQ0kgSG9zdCBDb250cm9s
DQo+ID4gKyAgICAgICAgKiByZWdpc3RlciBhbmQgY2xlYXIgQ2FyZCBEZXRlY3QgVGVzdCBMZXZl
bCBiaXQgaW4gU0RIQ0kgSG9zdA0KPiA+ICsgICAgICAgICogQ29udHJvbCByZWdpc3Rlci4NCj4g
PiArICAgICAgICAqLw0KPiANCj4gSXNuJ3QgdGhpcyBhIGNsZWFyZXIgZXhwbGFuYXRpb24sIGlm
IEkgdW5kZXJzdG9vZD8NCj4gDQo+ICJXaXRob3V0IHNldHRpbmcgQ0Qgc2VsZWN0IGFuZCB0ZXN0
IGJpdHMgbm93LCBTREhDSSBvbmx5IHdvcmtzIHdpdGggSlRBRw0KPiBjb25uZWN0ZWQuIg0KPiAN
Cj4gPiArICAgICAgIGN0cmwgJj0gflNESENJX0NUUkxfQ0RUTFZMOw0KPiA+ICsgICAgICAgY3Ry
bCB8PSBTREhDSV9DVFJMX0NEU1NFTDsNCj4gPiArICAgICAgIHNkaGNpX3dyaXRlYihob3N0LCBj
dHJsLCBTREhDSV9IT1NUX0NPTlRST0wpOw0KPiANCj4gQWxzby4uLiBpcyB0aGF0IGEgZmVhdHVy
ZSBvZiB0aGUgU0RIQ0kgSVAgb3IgdGhpcyBwYXJ0aWN1bGFyIGNoaXAncyBpbXBsZW1lbnRhdGlv
bg0KPiBvZiBpdD8gIEkgZ3Vlc3MgaWYgdGhlcmUgaXMgb25seSBvbmUgaW1wbGVtZW50YXRpb24g
cmlnaHQgbm93IHRoYXQgaGFzIHRoYXQNCj4gcmVzdHJpY3Rpb24gd29ycnkgYWJvdXQgbWFraW5n
IGl0IHNlbGVjdGFibGUgbGF0ZXIuICBCdXQgaWYgdGhlIGltcGxlbWVudGF0aW9uLCBpdA0KPiBt
aWdodCBtYWtlIHNlbnNlIHRvIGFsc28gcHV0IHRoZSBhZmZlY3RlZCBpbXBsZW1lbnRhdGlvbiBu
YW1lIGluIHRoZQ0KPiBjb21tZW50IHRvIG1ha2UgaXQgY2xlYXIuDQoNClRoaXMgaXMgYSBjaGlw
IGVycmF0YS4gSGF2aW5nIEpUQUcgY29ubmVjdGVkIG1hc2tzIHRoZSBwcm9ibGVtLCBidXQgaXMg
b3RoZXJ3aXNlIGlycmVsZXZhbnQuIENvbW1lbnQgd2lsbCBiZSBjaGFuZ2VkIHRvOiAiQ0Qgc2Vs
ZWN0IGFuZCB0ZXN0IGJpdHMgbXVzdCBiZSBzZXQgZm9yIGVycmF0YSB3b3JrYXJvdW5kLiINCg0K
PiANCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIHVuc2lnbmVkIGludCBwaWMzMl9zZGhjaV9n
ZXRfcm8oc3RydWN0IHNkaGNpX2hvc3QgKmhvc3QpIHsNCj4gPiArICAgICAgIC8qDQo+ID4gKyAg
ICAgICAgKiBUaGUgU0RIQ0lfV1JJVEVfUFJPVEVDVCBiaXQgaXMgdW5zdGFibGUgb24gY3VycmVu
dCBoYXJkd2FyZSBzbyB3ZQ0KPiA+ICsgICAgICAgICogY2FuJ3QgZGVwZW5kIG9uIGl0cyB2YWx1
ZSBpbiBhbnkgd2F5Lg0KPiA+ICsgICAgICAgICovDQo+ID4gKyAgICAgICByZXR1cm4gMDsNCj4g
PiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCBzZGhjaV9vcHMgcGljMzJfc2Ro
Y2lfb3BzID0gew0KPiA+ICsgICAgICAgLmdldF9tYXhfY2xvY2sgPSBwaWMzMl9zZGhjaV9nZXRf
bWF4X2Nsb2NrLA0KPiA+ICsgICAgICAgLnNldF9jbG9jayA9IHNkaGNpX3NldF9jbG9jaywNCj4g
PiArICAgICAgIC5zZXRfYnVzX3dpZHRoID0gcGljMzJfc2RoY2lfc2V0X2J1c193aWR0aCwNCj4g
PiArICAgICAgIC5yZXNldCA9IHNkaGNpX3Jlc2V0LA0KPiA+ICsgICAgICAgLnNldF91aHNfc2ln
bmFsaW5nID0gc2RoY2lfc2V0X3Voc19zaWduYWxpbmcsDQo+ID4gKyAgICAgICAuZ2V0X3JvID0g
cGljMzJfc2RoY2lfZ2V0X3JvLA0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArc3RhdGljIHZvaWQgcGlj
MzJfc2RoY2lfc2hhcmVkX2J1cyhzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KSB7DQo+ID4g
KyAgICAgICBzdHJ1Y3Qgc2RoY2lfaG9zdCAqaG9zdCA9IHBsYXRmb3JtX2dldF9kcnZkYXRhKHBk
ZXYpOw0KPiA+ICsgICAgICAgdTMyIGJ1cyA9IHJlYWRsKGhvc3QtPmlvYWRkciArIFNESF9TSEFS
RURfQlVTX0NUUkwpOw0KPiA+ICsgICAgICAgdTMyIGNsa19waW5zID0gKGJ1cyAmIFNESF9TSEFS
RURfQlVTX05SX0NMS19QSU5TX01BU0spID4+IDA7DQo+ID4gKyAgICAgICB1MzIgaXJxX3BpbnMg
PSAoYnVzICYgU0RIX1NIQVJFRF9CVVNfTlJfSVJRX1BJTlNfTUFTSykgPj4gNDsNCj4gPiArDQo+
ID4gKyAgICAgICAvKiBzZWxlY3QgZmlyc3QgY2xvY2sgKi8NCj4gPiArICAgICAgIGlmIChjbGtf
cGlucyAmIDB4MSkNCj4gDQo+IEJJVCgwKT8gIEFsc28gYSBjb3VwbGUgb2YgbGluZXMgZG93bi4N
Cj4gDQo+ID4gKyAgICAgICAgICAgICAgIGJ1cyB8PSAoMHgxIDw8IFNESF9TSEFSRURfQlVTX0NM
S19QSU5TKTsNCj4gDQo+IEkga25vdyBpdCdzIHBvcHVsYXIgYnV0IHRoZXJlIGlzIG5vIG1lYW5p
bmcgb3IgdXNlIGluICIweDEiIHdoZXJlIHlvdSBjb3VsZCBqdXN0DQo+IHNheSAiMSIuDQo+IA0K
PiA+ICsgICAgICAgLyogc2VsZWN0IGZpcnN0IGludGVycnVwdCAqLw0KPiA+ICsgICAgICAgaWYg
KGlycV9waW5zICYgMHgxKQ0KPiA+ICsgICAgICAgICAgICAgICBidXMgfD0gKDB4MSA8PCBTREhf
U0hBUkVEX0JVU19JUlFfUElOUyk7DQo+IA0KPiBBcyBhYm92ZS4NCg0KQWNrLiBXaWxsIGNoYW5n
ZS4NCg0KPiANCj4gPiArICAgICAgIHdyaXRlbChidXMsIGhvc3QtPmlvYWRkciArIFNESF9TSEFS
RURfQlVTX0NUUkwpOyB9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IHBpYzMyX3NkaGNpX3Byb2Jl
X3BsYXRmb3JtKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYsDQo+ID4gKyAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJ1Y3QgcGljMzJfc2RoY2lfcGRhdGEgKnBkYXRh
KQ0KPiA+ICt7DQo+ID4gKyAgICAgICBpbnQgcmV0ID0gMDsNCj4gPiArICAgICAgIHUzMiBjYXBz
X3Nsb3RfdHlwZTsNCj4gPiArICAgICAgIHN0cnVjdCBzZGhjaV9ob3N0ICpob3N0ID0gcGxhdGZv
cm1fZ2V0X2RydmRhdGEocGRldik7DQo+ID4gKw0KPiA+ICsgICAgICAgLyogQ2hlY2sgY2FyZCBz
bG90IGNvbm5lY3RlZCBvbiBzaGFyZWQgYnVzLiAqLw0KPiA+ICsgICAgICAgaG9zdC0+Y2FwcyA9
IHJlYWRsKGhvc3QtPmlvYWRkciArIFNESENJX0NBUEFCSUxJVElFUyk7DQo+ID4gKyAgICAgICBj
YXBzX3Nsb3RfdHlwZSA9IChob3N0LT5jYXBzICYgU0RIX0NBUFNfU0RIX1NMT1RfVFlQRV9NQVNL
KSA+Pg0KPiAzMDsNCj4gPiArICAgICAgIGlmIChjYXBzX3Nsb3RfdHlwZSA9PSBTREhfU0xPVF9U
WVBFX1NIQVJFRF9CVVMpDQo+ID4gKyAgICAgICAgICAgICAgIHBpYzMyX3NkaGNpX3NoYXJlZF9i
dXMocGRldik7DQo+ID4gKw0KPiA+ICsgICAgICAgcmV0dXJuIHJldDsNCj4gPiArfQ0KPiA+ICsN
Cj4gPiArc3RhdGljIGludCBwaWMzMl9zZGhjaV9wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNl
ICpwZGV2KSB7DQo+ID4gKyAgICAgICBzdHJ1Y3QgZGV2aWNlICpkZXYgPSAmcGRldi0+ZGV2Ow0K
PiA+ICsgICAgICAgc3RydWN0IHNkaGNpX2hvc3QgKmhvc3Q7DQo+ID4gKyAgICAgICBzdHJ1Y3Qg
cmVzb3VyY2UgKmlvbWVtOw0KPiA+ICsgICAgICAgc3RydWN0IHBpYzMyX3NkaGNpX3BkYXRhICpz
ZGhjaV9wZGF0YTsNCj4gPiArICAgICAgIHN0cnVjdCBwaWMzMl9zZGhjaV9wbGF0Zm9ybV9kYXRh
ICpwbGF0X2RhdGE7DQo+ID4gKyAgICAgICB1bnNpZ25lZCBpbnQgY2xrX3JhdGUgPSAwOw0KPiA+
ICsgICAgICAgaW50IHJldDsNCj4gPiArICAgICAgIHN0cnVjdCBwaW5jdHJsICpwaW5jdHJsOw0K
PiANCj4gSXQncyBoYXJkbHkgY3JpdGljYWwgYnV0IGZvciBleHRyYSBnb2xkIHN0YXIgYXJyYW5n
aW5nIGxvY2FsIHZhcnMgaW4gbGVuZ3RoIG9yZGVyDQo+IChsb25nZXN0IGZpcnN0KSBpcyBuaWNl
Lg0KDQpBY2suDQoNCj4gDQo+ID4gKw0KPiA+ICsgICAgICAgaG9zdCA9IHNkaGNpX2FsbG9jX2hv
c3QoZGV2LCBzaXplb2YoKnNkaGNpX3BkYXRhKSk7DQo+ID4gKyAgICAgICBpZiAoSVNfRVJSKGhv
c3QpKSB7DQo+ID4gKyAgICAgICAgICAgICAgIHJldCA9IFBUUl9FUlIoaG9zdCk7DQo+ID4gKyAg
ICAgICAgICAgICAgIGRldl9lcnIoJnBkZXYtPmRldiwgImNhbm5vdCBhbGxvY2F0ZSBtZW1vcnkg
Zm9yIHNkaGNpXG4iKTsNCj4gPiArICAgICAgICAgICAgICAgZ290byBlcnI7DQo+ID4gKyAgICAg
ICB9DQo+ID4gKw0KPiA+ICsgICAgICAgc2RoY2lfcGRhdGEgPSBzZGhjaV9wcml2KGhvc3QpOw0K
PiA+ICsgICAgICAgc2RoY2lfcGRhdGEtPnBkZXYgPSBwZGV2Ow0KPiA+ICsgICAgICAgcGxhdGZv
cm1fc2V0X2RydmRhdGEocGRldiwgaG9zdCk7DQo+ID4gKw0KPiA+ICsgICAgICAgaW9tZW0gPSBw
bGF0Zm9ybV9nZXRfcmVzb3VyY2UocGRldiwgSU9SRVNPVVJDRV9NRU0sIDApOw0KPiA+ICsgICAg
ICAgaG9zdC0+aW9hZGRyID0gZGV2bV9pb3JlbWFwX3Jlc291cmNlKCZwZGV2LT5kZXYsIGlvbWVt
KTsNCj4gPiArICAgICAgIGlmIChJU19FUlIoaG9zdC0+aW9hZGRyKSkgew0KPiA+ICsgICAgICAg
ICAgICAgICByZXQgPSBQVFJfRVJSKGhvc3QtPmlvYWRkcik7DQo+ID4gKyAgICAgICAgICAgICAg
IGRldl9lcnIoJnBkZXYtPmRldiwgInVuYWJsZSB0byBtYXAgaW9tZW06ICVkXG4iLCByZXQpOw0K
PiA+ICsgICAgICAgICAgICAgICBnb3RvIGVycl9ob3N0Ow0KPiA+ICsgICAgICAgfQ0KPiA+ICsN
Cj4gPiArICAgICAgIHBsYXRfZGF0YSA9IHBkZXYtPmRldi5wbGF0Zm9ybV9kYXRhOw0KPiA+ICsg
ICAgICAgaWYgKHBsYXRfZGF0YSAmJiBwbGF0X2RhdGEtPnNldHVwX2RtYSkgew0KPiA+ICsgICAg
ICAgICAgICAgICByZXQgPSBwbGF0X2RhdGEtPnNldHVwX2RtYShBRE1BX0ZJRk9fUkRfVEhTSExE
LA0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBRE1BX0ZJ
Rk9fV1JfVEhTSExEKTsNCj4gPiArICAgICAgICAgICAgICAgaWYgKHJldCkNCj4gPiArICAgICAg
ICAgICAgICAgICAgICAgICBnb3RvIGVycl9ob3N0Ow0KPiA+ICsgICAgICAgfQ0KPiA+ICsNCj4g
PiArICAgICAgIHBpbmN0cmwgPSBkZXZtX3BpbmN0cmxfZ2V0X3NlbGVjdF9kZWZhdWx0KCZwZGV2
LT5kZXYpOw0KPiA+ICsgICAgICAgaWYgKElTX0VSUihwaW5jdHJsKSkgew0KPiA+ICsgICAgICAg
ICAgICAgICByZXQgPSBQVFJfRVJSKHBpbmN0cmwpOw0KPiA+ICsgICAgICAgICAgICAgICBkZXZf
d2FybigmcGRldi0+ZGV2LCAiTm8gcGluY3RybCBwcm92aWRlZCAlZFxuIiwgcmV0KTsNCj4gPiAr
ICAgICAgICAgICAgICAgaWYgKHJldCA9PSAtRVBST0JFX0RFRkVSKQ0KPiA+ICsgICAgICAgICAg
ICAgICAgICAgICAgIGdvdG8gZXJyX2hvc3Q7DQo+ID4gKyAgICAgICB9DQo+ID4gKw0KPiA+ICsg
ICAgICAgaG9zdC0+b3BzID0gJnBpYzMyX3NkaGNpX29wczsNCj4gPiArICAgICAgIGhvc3QtPmly
cSA9IHBsYXRmb3JtX2dldF9pcnEocGRldiwgMCk7DQo+ID4gKw0KPiA+ICsgICAgICAgc2RoY2lf
cGRhdGEtPnN5c19jbGsgPSBkZXZtX2Nsa19nZXQoJnBkZXYtPmRldiwgInN5c19jbGsiKTsNCj4g
PiArICAgICAgIGlmIChJU19FUlIoc2RoY2lfcGRhdGEtPnN5c19jbGspKSB7DQo+ID4gKyAgICAg
ICAgICAgICAgIHJldCA9IFBUUl9FUlIoc2RoY2lfcGRhdGEtPnN5c19jbGspOw0KPiA+ICsgICAg
ICAgICAgICAgICBkZXZfZXJyKCZwZGV2LT5kZXYsICJFcnJvciBnZXR0aW5nIGNsb2NrXG4iKTsN
Cj4gPiArICAgICAgICAgICAgICAgZ290byBlcnJfaG9zdDsNCj4gPiArICAgICAgIH0NCj4gPiAr
DQo+ID4gKyAgICAgICAvKiBFbmFibGUgY2xvY2sgd2hlbiBhdmFpbGFibGUhICovDQo+ID4gKyAg
ICAgICByZXQgPSBjbGtfcHJlcGFyZV9lbmFibGUoc2RoY2lfcGRhdGEtPnN5c19jbGspOw0KPiA+
ICsgICAgICAgaWYgKHJldCkgew0KPiA+ICsgICAgICAgICAgICAgICBkZXZfZGJnKCZwZGV2LT5k
ZXYsICJFcnJvciBlbmFibGluZyBjbG9ja1xuIik7DQo+IA0KPiBTaG91bGRuJ3QgdGhpcyBiZSBk
ZXZfZXJyKCk/ICBZb3UgZG9uJ3Qgc3Vydml2ZSBub3QgaGF2aW5nIHRoZSBjbG9jayBpbiB0aGUg
c3RhbnphDQo+IGFib3ZlLiAgU28gaWYgeW91IGhhdmUgdGhlIGNsb2NrLCB5b3Ugd291bGQgd2Fu
dCB0byBrbm93IGlmIGl0IGRpZG4ndCBkZWFsIHdpdGgNCj4gdGhlIGNsa19wcmVwYXJlX2VuYWJs
ZSgpLg0KPiANCj4gVGhlIGNvbW1lbnQgNCBsaW5lcyBhYm92ZSBpcyBhbHNvIHdyb25nIGlmIHNv
Lg0KDQpBY2suIA0KDQo+IA0KPiA+ICsgICAgICAgICAgICAgICBnb3RvIGVycl9ob3N0Ow0KPiA+
ICsgICAgICAgfQ0KPiA+ICsNCj4gPiArICAgICAgIC8qIFNESCBDTEsgZW5hYmxlICovDQo+ID4g
KyAgICAgICBzZGhjaV9wZGF0YS0+YmFzZV9jbGsgPSBkZXZtX2Nsa19nZXQoJnBkZXYtPmRldiwg
ImJhc2VfY2xrIik7DQo+ID4gKyAgICAgICBpZiAoSVNfRVJSKHNkaGNpX3BkYXRhLT5iYXNlX2Ns
aykpIHsNCj4gPiArICAgICAgICAgICAgICAgcmV0ID0gUFRSX0VSUihzZGhjaV9wZGF0YS0+YmFz
ZV9jbGspOw0KPiA+ICsgICAgICAgICAgICAgICBkZXZfZXJyKCZwZGV2LT5kZXYsICJFcnJvciBn
ZXR0aW5nIGNsb2NrXG4iKTsNCj4gPiArICAgICAgICAgICAgICAgZ290byBlcnJfaG9zdDsNCj4g
PiArICAgICAgIH0NCj4gPiArDQo+ID4gKyAgICAgICAvKiBFbmFibGUgY2xvY2sgd2hlbiBhdmFp
bGFibGUhICovDQo+ID4gKyAgICAgICByZXQgPSBjbGtfcHJlcGFyZV9lbmFibGUoc2RoY2lfcGRh
dGEtPmJhc2VfY2xrKTsNCj4gDQo+IEFnYWluIHRoZSBjb21tZW50IHNlZW1zIHdyb25nLg0KDQpB
Y2suDQoNCj4gDQo+ID4gKyAgICAgICBpZiAocmV0KSB7DQo+ID4gKyAgICAgICAgICAgICAgIGRl
dl9kYmcoJnBkZXYtPmRldiwgIkVycm9yIGVuYWJsaW5nIGNsb2NrXG4iKTsNCj4gDQo+IEFuZCBp
ZiBJIHVuZGVyc3Rvb2QgaXQsIGRldl9lcnIoKSBuZWVkZWQuDQoNCkFjay4NCg0KPiANCj4gPiAr
ICAgICAgICAgICAgICAgZ290byBlcnJfaG9zdDsNCj4gPiArICAgICAgIH0NCj4gPiArDQo+ID4g
KyAgICAgICBjbGtfcmF0ZSA9IGNsa19nZXRfcmF0ZShzZGhjaV9wZGF0YS0+YmFzZV9jbGspOw0K
PiA+ICsgICAgICAgZGV2X2RiZygmcGRldi0+ZGV2LCAiYmFzZSBjbG9jayBhdDogJXVcbiIsIGNs
a19yYXRlKTsNCj4gPiArICAgICAgIGNsa19yYXRlID0gY2xrX2dldF9yYXRlKHNkaGNpX3BkYXRh
LT5zeXNfY2xrKTsNCj4gPiArICAgICAgIGRldl9kYmcoJnBkZXYtPmRldiwgInN5cyBjbG9jayBh
dDogJXVcbiIsIGNsa19yYXRlKTsNCj4gPiArDQo+ID4gKyAgICAgICBob3N0LT5xdWlya3MyIHw9
IFNESENJX1FVSVJLMl9OT18xXzhfVjsNCj4gPiArDQo+IA0KPiBQcm9iYWJseSBjYW4gbG9zZSB0
aGUgYmxhbmsgbGluZS4NCg0KQWNrLg0KDQo+IA0KPiA+ICsgICAgICAgaG9zdC0+cXVpcmtzIHw9
IFNESENJX1FVSVJLX05PX0hJU1BEX0JJVDsNCj4gPiArDQo+ID4gKyAgICAgICByZXQgPSBtbWNf
b2ZfcGFyc2UoaG9zdC0+bW1jKTsNCj4gPiArICAgICAgIGlmIChyZXQpDQo+ID4gKyAgICAgICAg
ICAgICAgIGdvdG8gZXJyX2hvc3Q7DQo+ID4gKw0KPiA+ICsgICAgICAgcmV0ID0gcGljMzJfc2Ro
Y2lfcHJvYmVfcGxhdGZvcm0ocGRldiwgc2RoY2lfcGRhdGEpOw0KPiA+ICsgICAgICAgaWYgKHJl
dCkgew0KPiA+ICsgICAgICAgICAgICAgICBkZXZfZXJyKCZwZGV2LT5kZXYsICJmYWlsZWQgdG8g
cHJvYmUgcGxhdGZvcm0hXG4iKTsNCj4gPiArICAgICAgICAgICAgICAgZ290byBlcnJfaG9zdDsN
Cj4gPiArICAgICAgIH0NCj4gPiArDQo+ID4gKyAgICAgICByZXQgPSBzZGhjaV9hZGRfaG9zdCho
b3N0KTsNCj4gPiArICAgICAgIGlmIChyZXQpIHsNCj4gPiArICAgICAgICAgICAgICAgZGV2X2Ri
ZygmcGRldi0+ZGV2LCAiZXJyb3IgYWRkaW5nIGhvc3RcbiIpOw0KPiA+ICsgICAgICAgICAgICAg
ICBnb3RvIGVycl9ob3N0Ow0KPiA+ICsgICAgICAgfQ0KPiA+ICsNCj4gPiArICAgICAgIGRldl9p
bmZvKCZwZGV2LT5kZXYsICJTdWNjZXNzZnVsbHkgYWRkZWQgc2RoY2kgaG9zdFxuIik7DQo+ID4g
KyAgICAgICByZXR1cm4gMDsNCj4gPiArDQo+ID4gK2Vycl9ob3N0Og0KPiA+ICsgICAgICAgc2Ro
Y2lfZnJlZV9ob3N0KGhvc3QpOw0KPiA+ICtlcnI6DQo+ID4gKyAgICAgICBkZXZfZXJyKCZwZGV2
LT5kZXYsICJwaWMzMi1zZGhjaSBwcm9iZSBmYWlsZWQ6ICVkXG4iLCByZXQpOw0KPiA+ICsgICAg
ICAgcmV0dXJuIHJldDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBwaWMzMl9zZGhj
aV9yZW1vdmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikgew0KPiA+ICsgICAgICAgc3Ry
dWN0IHNkaGNpX2hvc3QgKmhvc3QgPSBwbGF0Zm9ybV9nZXRfZHJ2ZGF0YShwZGV2KTsNCj4gPiAr
ICAgICAgIHN0cnVjdCBwaWMzMl9zZGhjaV9wZGF0YSAqc2RoY2lfcGRhdGEgPSBzZGhjaV9wcml2
KGhvc3QpOw0KPiA+ICsgICAgICAgaW50IGRlYWQgPSAwOw0KPiA+ICsgICAgICAgdTMyIHNjcmF0
Y2g7DQo+ID4gKw0KPiA+ICsgICAgICAgc2NyYXRjaCA9IHJlYWRsKGhvc3QtPmlvYWRkciArIFNE
SENJX0lOVF9TVEFUVVMpOw0KPiA+ICsgICAgICAgaWYgKHNjcmF0Y2ggPT0gKHUzMiktMSkNCj4g
DQo+IFNpbmNlIGl0J3Mgbm90IGFjdHVhbGx5IHJlbGF0ZWQgdG8gc2lnbmVkLCAodTMyKX4wIG1p
Z2h0IGJlIGNsZWFyZXIuDQoNCkFjay4NCg0KPiANCj4gPiArICAgICAgICAgICAgICAgZGVhZCA9
IDE7DQo+ID4gKw0KPiA+ICsgICAgICAgc2RoY2lfcmVtb3ZlX2hvc3QoaG9zdCwgZGVhZCk7DQo+
IA0KPiBZb3UgY291bGQgZ2V0IHJpZCBvZiAiZGVhZCIgYW5kIGhhdmUNCj4gDQo+ICAgICAgICAg
IHNkaGNpX3JlbW92ZV9ob3N0KGhvc3QsIHNjcmF0Y2ggPT0gKHUzMil+MCk7DQoNCkFjay4gDQoN
Cj4gDQo+ID4gKyAgICAgICBjbGtfZGlzYWJsZV91bnByZXBhcmUoc2RoY2lfcGRhdGEtPmJhc2Vf
Y2xrKTsNCj4gPiArICAgICAgIGNsa19kaXNhYmxlX3VucHJlcGFyZShzZGhjaV9wZGF0YS0+c3lz
X2Nsayk7DQo+ID4gKyAgICAgICBzZGhjaV9mcmVlX2hvc3QoaG9zdCk7DQo+ID4gKw0KPiA+ICsg
ICAgICAgcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qg
b2ZfZGV2aWNlX2lkIHBpYzMyX3NkaGNpX2lkX3RhYmxlW10gPSB7DQo+ID4gKyAgICAgICB7IC5j
b21wYXRpYmxlID0gIm1pY3JvY2hpcCxwaWMzMm16ZGEtc2RoY2kiIH0sDQo+ID4gKyAgICAgICB7
fQ0KPiA+ICt9Ow0KPiA+ICtNT0RVTEVfREVWSUNFX1RBQkxFKG9mLCBwaWMzMl9zZGhjaV9pZF90
YWJsZSk7DQo+ID4gKw0KPiA+ICtzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBwaWMzMl9z
ZGhjaV9kcml2ZXIgPSB7DQo+ID4gKyAgICAgICAuZHJpdmVyID0gew0KPiA+ICsgICAgICAgICAg
ICAgICAubmFtZSAgID0gREVWX05BTUUsDQo+ID4gKyAgICAgICAgICAgICAgIC5vd25lciAgPSBU
SElTX01PRFVMRSwNCj4gPiArICAgICAgICAgICAgICAgLm9mX21hdGNoX3RhYmxlID0gb2ZfbWF0
Y2hfcHRyKHBpYzMyX3NkaGNpX2lkX3RhYmxlKSwNCj4gPiArICAgICAgIH0sDQo+ID4gKyAgICAg
ICAucHJvYmUgICAgICAgICAgPSBwaWMzMl9zZGhjaV9wcm9iZSwNCj4gPiArICAgICAgIC5yZW1v
dmUgICAgICAgICA9IHBpYzMyX3NkaGNpX3JlbW92ZSwNCj4gPiArfTsNCj4gPiArDQo+ID4gK21v
ZHVsZV9wbGF0Zm9ybV9kcml2ZXIocGljMzJfc2RoY2lfZHJpdmVyKTsNCj4gPiArDQo+ID4gK01P
RFVMRV9ERVNDUklQVElPTigiTWljcm9jaGlwIFBJQzMyIFNESENJIGRyaXZlciIpOw0KPiA+ICtN
T0RVTEVfQVVUSE9SKCJQaXN0aXJpY2EgU29yaW4gQW5kcmVpICYgU2FuZGVlcCBTaGVyaWtlciIp
Ow0KPiA+ICtNT0RVTEVfTElDRU5TRSgiR1BMIHYyIik7DQo+ID4gLS0NCj4gPiAxLjcuOS41DQo+
ID4NCg0KVGhhbmtzLA0KUGF1bA0K
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1292885 — Re: [PATCH v2 12/14] mmc: sdhci-pic32: Add PIC32 SDHCI host controller driver

FromUlf Hansson <ulf.hansson@linaro.org>
Date2015-12-16 11:50 +0100
SubjectRe: [PATCH v2 12/14] mmc: sdhci-pic32: Add PIC32 SDHCI host controller driver
Message-ID<qGhOF-De-3@gated-at.bofh.it>
In reply to#1291661
[...]

> +static int pic32_sdhci_probe(struct platform_device *pdev)
> +{
> +       struct device *dev = &pdev->dev;
> +       struct sdhci_host *host;
> +       struct resource *iomem;
> +       struct pic32_sdhci_pdata *sdhci_pdata;
> +       struct pic32_sdhci_platform_data *plat_data;
> +       unsigned int clk_rate = 0;
> +       int ret;
> +       struct pinctrl *pinctrl;
> +
> +       host = sdhci_alloc_host(dev, sizeof(*sdhci_pdata));
> +       if (IS_ERR(host)) {
> +               ret = PTR_ERR(host);
> +               dev_err(&pdev->dev, "cannot allocate memory for sdhci\n");
> +               goto err;
> +       }
> +
> +       sdhci_pdata = sdhci_priv(host);
> +       sdhci_pdata->pdev = pdev;
> +       platform_set_drvdata(pdev, host);
> +
> +       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       host->ioaddr = devm_ioremap_resource(&pdev->dev, iomem);
> +       if (IS_ERR(host->ioaddr)) {
> +               ret = PTR_ERR(host->ioaddr);
> +               dev_err(&pdev->dev, "unable to map iomem: %d\n", ret);
> +               goto err_host;
> +       }
> +
> +       plat_data = pdev->dev.platform_data;
> +       if (plat_data && plat_data->setup_dma) {
> +               ret = plat_data->setup_dma(ADMA_FIFO_RD_THSHLD,
> +                                          ADMA_FIFO_WR_THSHLD);
> +               if (ret)
> +                       goto err_host;
> +       }
> +
> +       pinctrl = devm_pinctrl_get_select_default(&pdev->dev);

This isn't need as it's already handled by the PM core.

> +       if (IS_ERR(pinctrl)) {
> +               ret = PTR_ERR(pinctrl);
> +               dev_warn(&pdev->dev, "No pinctrl provided %d\n", ret);
> +               if (ret == -EPROBE_DEFER)
> +                       goto err_host;
> +       }
> +
> +       host->ops = &pic32_sdhci_ops;
> +       host->irq = platform_get_irq(pdev, 0);
> +
> +       sdhci_pdata->sys_clk = devm_clk_get(&pdev->dev, "sys_clk");
> +       if (IS_ERR(sdhci_pdata->sys_clk)) {
> +               ret = PTR_ERR(sdhci_pdata->sys_clk);
> +               dev_err(&pdev->dev, "Error getting clock\n");
> +               goto err_host;
> +       }
> +
> +       /* Enable clock when available! */
> +       ret = clk_prepare_enable(sdhci_pdata->sys_clk);
> +       if (ret) {
> +               dev_dbg(&pdev->dev, "Error enabling clock\n");
> +               goto err_host;
> +       }
> +
> +       /* SDH CLK enable */
> +       sdhci_pdata->base_clk = devm_clk_get(&pdev->dev, "base_clk");
> +       if (IS_ERR(sdhci_pdata->base_clk)) {
> +               ret = PTR_ERR(sdhci_pdata->base_clk);
> +               dev_err(&pdev->dev, "Error getting clock\n");
> +               goto err_host;
> +       }
> +
> +       /* Enable clock when available! */
> +       ret = clk_prepare_enable(sdhci_pdata->base_clk);
> +       if (ret) {
> +               dev_dbg(&pdev->dev, "Error enabling clock\n");
> +               goto err_host;
> +       }
> +
> +       clk_rate = clk_get_rate(sdhci_pdata->base_clk);
> +       dev_dbg(&pdev->dev, "base clock at: %u\n", clk_rate);
> +       clk_rate = clk_get_rate(sdhci_pdata->sys_clk);
> +       dev_dbg(&pdev->dev, "sys clock at: %u\n", clk_rate);

This looks like some leftover from a debugging task. Can you remove them?

> +
> +       host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
> +
> +       host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
> +
> +       ret = mmc_of_parse(host->mmc);
> +       if (ret)

From this point, the error handling doesn't undo clk_prepare_enable().
Please add that.

> +               goto err_host;
> +
> +       ret = pic32_sdhci_probe_platform(pdev, sdhci_pdata);
> +       if (ret) {
> +               dev_err(&pdev->dev, "failed to probe platform!\n");
> +               goto err_host;
> +       }
> +
> +       ret = sdhci_add_host(host);
> +       if (ret) {
> +               dev_dbg(&pdev->dev, "error adding host\n");
> +               goto err_host;
> +       }
> +
> +       dev_info(&pdev->dev, "Successfully added sdhci host\n");
> +       return 0;
> +
> +err_host:
> +       sdhci_free_host(host);
> +err:
> +       dev_err(&pdev->dev, "pic32-sdhci probe failed: %d\n", ret);
> +       return ret;

A general comment for the ->probe() and the below ->remove() callback,
is that you should probably be able to convert to use
sdhci_pltfm_init() and sdhci_pltfm_free() in favor of
sdhci_alloc_host() and sdhci_free_host().

I think that could simplify the code a bit.

> +}
> +
> +static int pic32_sdhci_remove(struct platform_device *pdev)
> +{
> +       struct sdhci_host *host = platform_get_drvdata(pdev);
> +       struct pic32_sdhci_pdata *sdhci_pdata = sdhci_priv(host);
> +       int dead = 0;
> +       u32 scratch;
> +
> +       scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
> +       if (scratch == (u32)-1)
> +               dead = 1;
> +
> +       sdhci_remove_host(host, dead);
> +       clk_disable_unprepare(sdhci_pdata->base_clk);
> +       clk_disable_unprepare(sdhci_pdata->sys_clk);
> +       sdhci_free_host(host);
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id pic32_sdhci_id_table[] = {
> +       { .compatible = "microchip,pic32mzda-sdhci" },
> +       {}
> +};
> +MODULE_DEVICE_TABLE(of, pic32_sdhci_id_table);
> +
> +static struct platform_driver pic32_sdhci_driver = {
> +       .driver = {
> +               .name   = DEV_NAME,
> +               .owner  = THIS_MODULE,
> +               .of_match_table = of_match_ptr(pic32_sdhci_id_table),
> +       },
> +       .probe          = pic32_sdhci_probe,
> +       .remove         = pic32_sdhci_remove,
> +};
> +
> +module_platform_driver(pic32_sdhci_driver);
> +
> +MODULE_DESCRIPTION("Microchip PIC32 SDHCI driver");
> +MODULE_AUTHOR("Pistirica Sorin Andrei & Sandeep Sheriker");
> +MODULE_LICENSE("GPL v2");
> --
> 1.7.9.5
>

Kind regards
Uffe
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1294110 — RE: [PATCH v2 12/14] mmc: sdhci-pic32: Add PIC32 SDHCI host controller driver

From<Paul.Thacker@microchip.com>
Date2015-12-17 19:10 +0100
SubjectRE: [PATCH v2 12/14] mmc: sdhci-pic32: Add PIC32 SDHCI host controller driver
Message-ID<qGLa2-2TY-13@gated-at.bofh.it>
In reply to#1292885
T24gMTIvMTYvMjAxNSAzOjQ4IEFNLCBVbGYgSGFuc3NvbiB3cm90ZToNCj4gDQo+IFsuLi5dDQo+
IA0KPiA+ICtzdGF0aWMgaW50IHBpYzMyX3NkaGNpX3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZp
Y2UgKnBkZXYpIHsNCj4gPiArICAgICAgIHN0cnVjdCBkZXZpY2UgKmRldiA9ICZwZGV2LT5kZXY7
DQo+ID4gKyAgICAgICBzdHJ1Y3Qgc2RoY2lfaG9zdCAqaG9zdDsNCj4gPiArICAgICAgIHN0cnVj
dCByZXNvdXJjZSAqaW9tZW07DQo+ID4gKyAgICAgICBzdHJ1Y3QgcGljMzJfc2RoY2lfcGRhdGEg
KnNkaGNpX3BkYXRhOw0KPiA+ICsgICAgICAgc3RydWN0IHBpYzMyX3NkaGNpX3BsYXRmb3JtX2Rh
dGEgKnBsYXRfZGF0YTsNCj4gPiArICAgICAgIHVuc2lnbmVkIGludCBjbGtfcmF0ZSA9IDA7DQo+
ID4gKyAgICAgICBpbnQgcmV0Ow0KPiA+ICsgICAgICAgc3RydWN0IHBpbmN0cmwgKnBpbmN0cmw7
DQo+ID4gKw0KPiA+ICsgICAgICAgaG9zdCA9IHNkaGNpX2FsbG9jX2hvc3QoZGV2LCBzaXplb2Yo
KnNkaGNpX3BkYXRhKSk7DQo+ID4gKyAgICAgICBpZiAoSVNfRVJSKGhvc3QpKSB7DQo+ID4gKyAg
ICAgICAgICAgICAgIHJldCA9IFBUUl9FUlIoaG9zdCk7DQo+ID4gKyAgICAgICAgICAgICAgIGRl
dl9lcnIoJnBkZXYtPmRldiwgImNhbm5vdCBhbGxvY2F0ZSBtZW1vcnkgZm9yIHNkaGNpXG4iKTsN
Cj4gPiArICAgICAgICAgICAgICAgZ290byBlcnI7DQo+ID4gKyAgICAgICB9DQo+ID4gKw0KPiA+
ICsgICAgICAgc2RoY2lfcGRhdGEgPSBzZGhjaV9wcml2KGhvc3QpOw0KPiA+ICsgICAgICAgc2Ro
Y2lfcGRhdGEtPnBkZXYgPSBwZGV2Ow0KPiA+ICsgICAgICAgcGxhdGZvcm1fc2V0X2RydmRhdGEo
cGRldiwgaG9zdCk7DQo+ID4gKw0KPiA+ICsgICAgICAgaW9tZW0gPSBwbGF0Zm9ybV9nZXRfcmVz
b3VyY2UocGRldiwgSU9SRVNPVVJDRV9NRU0sIDApOw0KPiA+ICsgICAgICAgaG9zdC0+aW9hZGRy
ID0gZGV2bV9pb3JlbWFwX3Jlc291cmNlKCZwZGV2LT5kZXYsIGlvbWVtKTsNCj4gPiArICAgICAg
IGlmIChJU19FUlIoaG9zdC0+aW9hZGRyKSkgew0KPiA+ICsgICAgICAgICAgICAgICByZXQgPSBQ
VFJfRVJSKGhvc3QtPmlvYWRkcik7DQo+ID4gKyAgICAgICAgICAgICAgIGRldl9lcnIoJnBkZXYt
PmRldiwgInVuYWJsZSB0byBtYXAgaW9tZW06ICVkXG4iLCByZXQpOw0KPiA+ICsgICAgICAgICAg
ICAgICBnb3RvIGVycl9ob3N0Ow0KPiA+ICsgICAgICAgfQ0KPiA+ICsNCj4gPiArICAgICAgIHBs
YXRfZGF0YSA9IHBkZXYtPmRldi5wbGF0Zm9ybV9kYXRhOw0KPiA+ICsgICAgICAgaWYgKHBsYXRf
ZGF0YSAmJiBwbGF0X2RhdGEtPnNldHVwX2RtYSkgew0KPiA+ICsgICAgICAgICAgICAgICByZXQg
PSBwbGF0X2RhdGEtPnNldHVwX2RtYShBRE1BX0ZJRk9fUkRfVEhTSExELA0KPiA+ICsgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBRE1BX0ZJRk9fV1JfVEhTSExEKTsN
Cj4gPiArICAgICAgICAgICAgICAgaWYgKHJldCkNCj4gPiArICAgICAgICAgICAgICAgICAgICAg
ICBnb3RvIGVycl9ob3N0Ow0KPiA+ICsgICAgICAgfQ0KPiA+ICsNCj4gPiArICAgICAgIHBpbmN0
cmwgPSBkZXZtX3BpbmN0cmxfZ2V0X3NlbGVjdF9kZWZhdWx0KCZwZGV2LT5kZXYpOw0KPiANCj4g
VGhpcyBpc24ndCBuZWVkIGFzIGl0J3MgYWxyZWFkeSBoYW5kbGVkIGJ5IHRoZSBQTSBjb3JlLg0K
DQpBY2suIFdpbGwgcmVtb3ZlLg0KDQo+IA0KPiA+ICsgICAgICAgaWYgKElTX0VSUihwaW5jdHJs
KSkgew0KPiA+ICsgICAgICAgICAgICAgICByZXQgPSBQVFJfRVJSKHBpbmN0cmwpOw0KPiA+ICsg
ICAgICAgICAgICAgICBkZXZfd2FybigmcGRldi0+ZGV2LCAiTm8gcGluY3RybCBwcm92aWRlZCAl
ZFxuIiwgcmV0KTsNCj4gPiArICAgICAgICAgICAgICAgaWYgKHJldCA9PSAtRVBST0JFX0RFRkVS
KQ0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIGdvdG8gZXJyX2hvc3Q7DQo+ID4gKyAgICAg
ICB9DQo+ID4gKw0KPiA+ICsgICAgICAgaG9zdC0+b3BzID0gJnBpYzMyX3NkaGNpX29wczsNCj4g
PiArICAgICAgIGhvc3QtPmlycSA9IHBsYXRmb3JtX2dldF9pcnEocGRldiwgMCk7DQo+ID4gKw0K
PiA+ICsgICAgICAgc2RoY2lfcGRhdGEtPnN5c19jbGsgPSBkZXZtX2Nsa19nZXQoJnBkZXYtPmRl
diwgInN5c19jbGsiKTsNCj4gPiArICAgICAgIGlmIChJU19FUlIoc2RoY2lfcGRhdGEtPnN5c19j
bGspKSB7DQo+ID4gKyAgICAgICAgICAgICAgIHJldCA9IFBUUl9FUlIoc2RoY2lfcGRhdGEtPnN5
c19jbGspOw0KPiA+ICsgICAgICAgICAgICAgICBkZXZfZXJyKCZwZGV2LT5kZXYsICJFcnJvciBn
ZXR0aW5nIGNsb2NrXG4iKTsNCj4gPiArICAgICAgICAgICAgICAgZ290byBlcnJfaG9zdDsNCj4g
PiArICAgICAgIH0NCj4gPiArDQo+ID4gKyAgICAgICAvKiBFbmFibGUgY2xvY2sgd2hlbiBhdmFp
bGFibGUhICovDQo+ID4gKyAgICAgICByZXQgPSBjbGtfcHJlcGFyZV9lbmFibGUoc2RoY2lfcGRh
dGEtPnN5c19jbGspOw0KPiA+ICsgICAgICAgaWYgKHJldCkgew0KPiA+ICsgICAgICAgICAgICAg
ICBkZXZfZGJnKCZwZGV2LT5kZXYsICJFcnJvciBlbmFibGluZyBjbG9ja1xuIik7DQo+ID4gKyAg
ICAgICAgICAgICAgIGdvdG8gZXJyX2hvc3Q7DQo+ID4gKyAgICAgICB9DQo+ID4gKw0KPiA+ICsg
ICAgICAgLyogU0RIIENMSyBlbmFibGUgKi8NCj4gPiArICAgICAgIHNkaGNpX3BkYXRhLT5iYXNl
X2NsayA9IGRldm1fY2xrX2dldCgmcGRldi0+ZGV2LCAiYmFzZV9jbGsiKTsNCj4gPiArICAgICAg
IGlmIChJU19FUlIoc2RoY2lfcGRhdGEtPmJhc2VfY2xrKSkgew0KPiA+ICsgICAgICAgICAgICAg
ICByZXQgPSBQVFJfRVJSKHNkaGNpX3BkYXRhLT5iYXNlX2Nsayk7DQo+ID4gKyAgICAgICAgICAg
ICAgIGRldl9lcnIoJnBkZXYtPmRldiwgIkVycm9yIGdldHRpbmcgY2xvY2tcbiIpOw0KPiA+ICsg
ICAgICAgICAgICAgICBnb3RvIGVycl9ob3N0Ow0KPiA+ICsgICAgICAgfQ0KPiA+ICsNCj4gPiAr
ICAgICAgIC8qIEVuYWJsZSBjbG9jayB3aGVuIGF2YWlsYWJsZSEgKi8NCj4gPiArICAgICAgIHJl
dCA9IGNsa19wcmVwYXJlX2VuYWJsZShzZGhjaV9wZGF0YS0+YmFzZV9jbGspOw0KPiA+ICsgICAg
ICAgaWYgKHJldCkgew0KPiA+ICsgICAgICAgICAgICAgICBkZXZfZGJnKCZwZGV2LT5kZXYsICJF
cnJvciBlbmFibGluZyBjbG9ja1xuIik7DQo+ID4gKyAgICAgICAgICAgICAgIGdvdG8gZXJyX2hv
c3Q7DQo+ID4gKyAgICAgICB9DQo+ID4gKw0KPiA+ICsgICAgICAgY2xrX3JhdGUgPSBjbGtfZ2V0
X3JhdGUoc2RoY2lfcGRhdGEtPmJhc2VfY2xrKTsNCj4gPiArICAgICAgIGRldl9kYmcoJnBkZXYt
PmRldiwgImJhc2UgY2xvY2sgYXQ6ICV1XG4iLCBjbGtfcmF0ZSk7DQo+ID4gKyAgICAgICBjbGtf
cmF0ZSA9IGNsa19nZXRfcmF0ZShzZGhjaV9wZGF0YS0+c3lzX2Nsayk7DQo+ID4gKyAgICAgICBk
ZXZfZGJnKCZwZGV2LT5kZXYsICJzeXMgY2xvY2sgYXQ6ICV1XG4iLCBjbGtfcmF0ZSk7DQo+IA0K
PiBUaGlzIGxvb2tzIGxpa2Ugc29tZSBsZWZ0b3ZlciBmcm9tIGEgZGVidWdnaW5nIHRhc2suIENh
biB5b3UgcmVtb3ZlIHRoZW0/DQo+IA0KDQpZZXMsIHRoZXNlIGFyZSBub3QgbmVlZGVkIGFuZCB3
aWxsIGJlIHJlbW92ZWQuDQoNCj4gPiArDQo+ID4gKyAgICAgICBob3N0LT5xdWlya3MyIHw9IFNE
SENJX1FVSVJLMl9OT18xXzhfVjsNCj4gPiArDQo+ID4gKyAgICAgICBob3N0LT5xdWlya3MgfD0g
U0RIQ0lfUVVJUktfTk9fSElTUERfQklUOw0KPiA+ICsNCj4gPiArICAgICAgIHJldCA9IG1tY19v
Zl9wYXJzZShob3N0LT5tbWMpOw0KPiA+ICsgICAgICAgaWYgKHJldCkNCj4gDQo+IEZyb20gdGhp
cyBwb2ludCwgdGhlIGVycm9yIGhhbmRsaW5nIGRvZXNuJ3QgdW5kbyBjbGtfcHJlcGFyZV9lbmFi
bGUoKS4NCj4gUGxlYXNlIGFkZCB0aGF0Lg0KDQpBY2suIFdpbGwgZG8uDQoNCj4gDQo+ID4gKyAg
ICAgICAgICAgICAgIGdvdG8gZXJyX2hvc3Q7DQo+ID4gKw0KPiA+ICsgICAgICAgcmV0ID0gcGlj
MzJfc2RoY2lfcHJvYmVfcGxhdGZvcm0ocGRldiwgc2RoY2lfcGRhdGEpOw0KPiA+ICsgICAgICAg
aWYgKHJldCkgew0KPiA+ICsgICAgICAgICAgICAgICBkZXZfZXJyKCZwZGV2LT5kZXYsICJmYWls
ZWQgdG8gcHJvYmUgcGxhdGZvcm0hXG4iKTsNCj4gPiArICAgICAgICAgICAgICAgZ290byBlcnJf
aG9zdDsNCj4gPiArICAgICAgIH0NCj4gPiArDQo+ID4gKyAgICAgICByZXQgPSBzZGhjaV9hZGRf
aG9zdChob3N0KTsNCj4gPiArICAgICAgIGlmIChyZXQpIHsNCj4gPiArICAgICAgICAgICAgICAg
ZGV2X2RiZygmcGRldi0+ZGV2LCAiZXJyb3IgYWRkaW5nIGhvc3RcbiIpOw0KPiA+ICsgICAgICAg
ICAgICAgICBnb3RvIGVycl9ob3N0Ow0KPiA+ICsgICAgICAgfQ0KPiA+ICsNCj4gPiArICAgICAg
IGRldl9pbmZvKCZwZGV2LT5kZXYsICJTdWNjZXNzZnVsbHkgYWRkZWQgc2RoY2kgaG9zdFxuIik7
DQo+ID4gKyAgICAgICByZXR1cm4gMDsNCj4gPiArDQo+ID4gK2Vycl9ob3N0Og0KPiA+ICsgICAg
ICAgc2RoY2lfZnJlZV9ob3N0KGhvc3QpOw0KPiA+ICtlcnI6DQo+ID4gKyAgICAgICBkZXZfZXJy
KCZwZGV2LT5kZXYsICJwaWMzMi1zZGhjaSBwcm9iZSBmYWlsZWQ6ICVkXG4iLCByZXQpOw0KPiA+
ICsgICAgICAgcmV0dXJuIHJldDsNCj4gDQo+IEEgZ2VuZXJhbCBjb21tZW50IGZvciB0aGUgLT5w
cm9iZSgpIGFuZCB0aGUgYmVsb3cgLT5yZW1vdmUoKSBjYWxsYmFjaywgaXMgdGhhdA0KPiB5b3Ug
c2hvdWxkIHByb2JhYmx5IGJlIGFibGUgdG8gY29udmVydCB0byB1c2UNCj4gc2RoY2lfcGx0Zm1f
aW5pdCgpIGFuZCBzZGhjaV9wbHRmbV9mcmVlKCkgaW4gZmF2b3Igb2YNCj4gc2RoY2lfYWxsb2Nf
aG9zdCgpIGFuZCBzZGhjaV9mcmVlX2hvc3QoKS4NCj4gDQo+IEkgdGhpbmsgdGhhdCBjb3VsZCBz
aW1wbGlmeSB0aGUgY29kZSBhIGJpdC4NCg0KT2suIFdpbGwgZG8uDQoNCj4gDQo+ID4gK30NCj4g
PiArDQo+ID4gK3N0YXRpYyBpbnQgcGljMzJfc2RoY2lfcmVtb3ZlKHN0cnVjdCBwbGF0Zm9ybV9k
ZXZpY2UgKnBkZXYpIHsNCj4gPiArICAgICAgIHN0cnVjdCBzZGhjaV9ob3N0ICpob3N0ID0gcGxh
dGZvcm1fZ2V0X2RydmRhdGEocGRldik7DQo+ID4gKyAgICAgICBzdHJ1Y3QgcGljMzJfc2RoY2lf
cGRhdGEgKnNkaGNpX3BkYXRhID0gc2RoY2lfcHJpdihob3N0KTsNCj4gPiArICAgICAgIGludCBk
ZWFkID0gMDsNCj4gPiArICAgICAgIHUzMiBzY3JhdGNoOw0KPiA+ICsNCj4gPiArICAgICAgIHNj
cmF0Y2ggPSByZWFkbChob3N0LT5pb2FkZHIgKyBTREhDSV9JTlRfU1RBVFVTKTsNCj4gPiArICAg
ICAgIGlmIChzY3JhdGNoID09ICh1MzIpLTEpDQo+ID4gKyAgICAgICAgICAgICAgIGRlYWQgPSAx
Ow0KPiA+ICsNCj4gPiArICAgICAgIHNkaGNpX3JlbW92ZV9ob3N0KGhvc3QsIGRlYWQpOw0KPiA+
ICsgICAgICAgY2xrX2Rpc2FibGVfdW5wcmVwYXJlKHNkaGNpX3BkYXRhLT5iYXNlX2Nsayk7DQo+
ID4gKyAgICAgICBjbGtfZGlzYWJsZV91bnByZXBhcmUoc2RoY2lfcGRhdGEtPnN5c19jbGspOw0K
PiA+ICsgICAgICAgc2RoY2lfZnJlZV9ob3N0KGhvc3QpOw0KPiA+ICsNCj4gPiArICAgICAgIHJl
dHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgY29uc3Qgc3RydWN0IG9mX2Rldmlj
ZV9pZCBwaWMzMl9zZGhjaV9pZF90YWJsZVtdID0gew0KPiA+ICsgICAgICAgeyAuY29tcGF0aWJs
ZSA9ICJtaWNyb2NoaXAscGljMzJtemRhLXNkaGNpIiB9LA0KPiA+ICsgICAgICAge30NCj4gPiAr
fTsNCj4gPiArTU9EVUxFX0RFVklDRV9UQUJMRShvZiwgcGljMzJfc2RoY2lfaWRfdGFibGUpOw0K
PiA+ICsNCj4gPiArc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kcml2ZXIgcGljMzJfc2RoY2lfZHJp
dmVyID0gew0KPiA+ICsgICAgICAgLmRyaXZlciA9IHsNCj4gPiArICAgICAgICAgICAgICAgLm5h
bWUgICA9IERFVl9OQU1FLA0KPiA+ICsgICAgICAgICAgICAgICAub3duZXIgID0gVEhJU19NT0RV
TEUsDQo+ID4gKyAgICAgICAgICAgICAgIC5vZl9tYXRjaF90YWJsZSA9IG9mX21hdGNoX3B0cihw
aWMzMl9zZGhjaV9pZF90YWJsZSksDQo+ID4gKyAgICAgICB9LA0KPiA+ICsgICAgICAgLnByb2Jl
ICAgICAgICAgID0gcGljMzJfc2RoY2lfcHJvYmUsDQo+ID4gKyAgICAgICAucmVtb3ZlICAgICAg
ICAgPSBwaWMzMl9zZGhjaV9yZW1vdmUsDQo+ID4gK307DQo+ID4gKw0KPiA+ICttb2R1bGVfcGxh
dGZvcm1fZHJpdmVyKHBpYzMyX3NkaGNpX2RyaXZlcik7DQo+ID4gKw0KPiA+ICtNT0RVTEVfREVT
Q1JJUFRJT04oIk1pY3JvY2hpcCBQSUMzMiBTREhDSSBkcml2ZXIiKTsNCj4gPiArTU9EVUxFX0FV
VEhPUigiUGlzdGlyaWNhIFNvcmluIEFuZHJlaSAmIFNhbmRlZXAgU2hlcmlrZXIiKTsNCj4gPiAr
TU9EVUxFX0xJQ0VOU0UoIkdQTCB2MiIpOw0KPiA+IC0tDQo+ID4gMS43LjkuNQ0KDQpUaGFua3Ms
DQpQYXVsDQo=
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1291662 — [PATCH v2 10/14] serial: pic32_uart: Add PIC32 UART driver

FromJoshua Henderson <joshua.henderson@microchip.com>
Date2015-12-14 23:50 +0100
Subject[PATCH v2 10/14] serial: pic32_uart: Add PIC32 UART driver
Message-ID<qFK6n-3W4-35@gated-at.bofh.it>
In reply to#1291644
From: Andrei Pistirica <andrei.pistirica@microchip.com>

This adds UART and a serial console driver for Microchip PIC32 class
devices.

Signed-off-by: Andrei Pistirica <andrei.pistirica@microchip.com>
Signed-off-by: Joshua Henderson <joshua.henderson@microchip.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
---
 drivers/tty/serial/Kconfig       |   21 +
 drivers/tty/serial/Makefile      |    1 +
 drivers/tty/serial/pic32_uart.c  |  927 ++++++++++++++++++++++++++++++++++++++
 drivers/tty/serial/pic32_uart.h  |  198 ++++++++
 include/uapi/linux/serial_core.h |    3 +
 5 files changed, 1150 insertions(+)
 create mode 100644 drivers/tty/serial/pic32_uart.c
 create mode 100644 drivers/tty/serial/pic32_uart.h

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index f38beb2..8853b1e 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -901,6 +901,27 @@ config SERIAL_SGI_L1_CONSOLE
 		controller serial port as your console (you want this!),
 		say Y.  Otherwise, say N.
 
+config SERIAL_PIC32
+	tristate "Microchip PIC32 serial support"
+	depends on MACH_PIC32
+	select SERIAL_CORE
+	help
+	  If you have a PIC32, this driver supports the serial ports.
+
+	  Say Y or M to use PIC32 serial ports, otherwise say N. Note that
+	  to use a serial port as a console, this must be included in kernel and
+	  not as a module.
+
+config SERIAL_PIC32_CONSOLE
+	bool "PIC32 serial console support"
+	depends on SERIAL_PIC32
+	select SERIAL_CORE_CONSOLE
+	help
+	  If you have a PIC32, this driver supports the putting a console on one
+	  of the serial ports.
+
+	  Say Y to use the PIC32 console, otherwise say N.
+
 config SERIAL_MPC52xx
 	tristate "Freescale MPC52xx/MPC512x family PSC serial support"
 	depends on PPC_MPC52xx || PPC_MPC512x
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 5ab4111..bc5e354 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -93,6 +93,7 @@ obj-$(CONFIG_SERIAL_CONEXANT_DIGICOLOR)	+= digicolor-usart.o
 obj-$(CONFIG_SERIAL_MEN_Z135)	+= men_z135_uart.o
 obj-$(CONFIG_SERIAL_SPRD) += sprd_serial.o
 obj-$(CONFIG_SERIAL_STM32)	+= stm32-usart.o
+obj-$(CONFIG_SERIAL_PIC32)	+= pic32_uart.o
 
 # GPIOLIB helpers for modem control lines
 obj-$(CONFIG_SERIAL_MCTRL_GPIO)	+= serial_mctrl_gpio.o
diff --git a/drivers/tty/serial/pic32_uart.c b/drivers/tty/serial/pic32_uart.c
new file mode 100644
index 0000000..5c05c11
--- /dev/null
+++ b/drivers/tty/serial/pic32_uart.c
@@ -0,0 +1,927 @@
+/*
+ * PIC32 Integrated Serial Driver.
+ *
+ * Copyright (C) 2015 Microchip Technology, Inc.
+ *
+ * Authors:
+ *   Steve Scott <steve.scott@microchip.com>,
+ *   Sorin-Andrei Pistirica <andrei.pistirica@microchip.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/console.h>
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/sysrq.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <uapi/linux/serial_core.h>
+#include <linux/delay.h>
+
+#include "pic32_uart.h"
+
+/* UART name and device definitions */
+#define PIC32_DEV_NAME		"pic32-uart"
+#define PIC32_MAX_UARTS		6
+
+#define PIC32_SDEV_NAME		"ttyS"
+#define PIC32_SDEV_MAJOR	TTY_MAJOR
+#define PIC32_SDEV_MINOR	64
+
+/* pic32_sport pointer for console use */
+static struct pic32_sport *pic32_sports[PIC32_MAX_UARTS];
+
+static inline int pic32_enable_clock(struct pic32_sport *sport)
+{
+	sport->ref_clk++;
+
+	return clk_prepare_enable(sport->clk);
+}
+
+static inline void pic32_disable_clock(struct pic32_sport *sport)
+{
+	sport->ref_clk--;
+	clk_disable_unprepare(sport->clk);
+}
+
+/* serial core request to check if uart tx buffer is empty */
+static unsigned int pic32_uart_tx_empty(struct uart_port *port)
+{
+	struct pic32_sport *sport = to_pic32_sport(port);
+	u32 val = pic32_uart_read(sport, PIC32_UART_STA);
+
+	return (val & PIC32_UART_STA_TRMT) ? 1 : 0;
+}
+
+/* serial core request to set UART outputs */
+static void pic32_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	struct pic32_sport *sport = to_pic32_sport(port);
+
+	/* set loopback mode */
+	if (mctrl & TIOCM_LOOP)
+		pic32_uart_rset(PIC32_UART_MODE_LPBK, sport, PIC32_UART_MODE);
+	else
+		pic32_uart_rclr(PIC32_UART_MODE_LPBK, sport, PIC32_UART_MODE);
+}
+
+/* get the state of CTS input pin for this port */
+static unsigned int get_cts_state(struct pic32_sport *sport)
+{
+	/* default state must be asserted */
+	int val = 1;
+
+	/* read and invert UxCTS */
+	if (gpio_is_valid(sport->cts_gpio))
+		val = !gpio_get_value(sport->cts_gpio);
+
+	return val;
+}
+
+/* serial core request to return the state of misc UART input pins */
+static unsigned int pic32_uart_get_mctrl(struct uart_port *port)
+{
+	struct pic32_sport *sport = to_pic32_sport(port);
+	unsigned int mctrl = 0;
+
+	if (!sport->hw_flow_ctrl) {
+		mctrl |= TIOCM_CTS;
+		goto ret;
+	}
+
+	if (get_cts_state(sport))
+		mctrl |= TIOCM_CTS;
+
+ret:
+	/* DSR and CD are not supported in PIC32, so return 1
+	 * RI is not supported in PIC32, so return 0
+	 */
+	mctrl |= TIOCM_CD;
+	mctrl |= TIOCM_DSR;
+
+	return mctrl;
+}
+
+/* stop tx and start tx are not called in pairs, therefore a flag indicates
+ * the status of irq to control the irq-depth.
+ */
+static inline void pic32_uart_irqtxen(struct pic32_sport *sport, u8 en)
+{
+	if (en && !tx_irq_enabled(sport)) {
+		enable_irq(sport->irq_tx);
+		tx_irq_enabled(sport) = 1;
+	} else if (!en && tx_irq_enabled(sport)) {
+		/* use disable_irq_nosync() and not disable_irq() to avoid self
+		 * imposed deadlock by not waiting for irq handler to end,
+		 * since this callback is called from interrupt context.
+		 */
+		disable_irq_nosync(sport->irq_tx);
+		tx_irq_enabled(sport) = 0;
+	}
+}
+
+/* serial core request to disable tx ASAP (used for flow control) */
+static void pic32_uart_stop_tx(struct uart_port *port)
+{
+	struct pic32_sport *sport = to_pic32_sport(port);
+
+	if (!(pic32_uart_read(sport, PIC32_UART_MODE) & PIC32_UART_MODE_ON))
+		return;
+
+	if (!(pic32_uart_read(sport, PIC32_UART_STA) & PIC32_UART_STA_UTXEN))
+		return;
+
+	/* wait for tx empty */
+	while (!(pic32_uart_read(sport, PIC32_UART_STA) & PIC32_UART_STA_TRMT))
+		udelay(1);
+
+	pic32_uart_rclr(PIC32_UART_STA_UTXEN, sport, PIC32_UART_STA);
+	pic32_uart_irqtxen(sport, 0);
+}
+
+/* serial core request to (re)enable tx */
+static void pic32_uart_start_tx(struct uart_port *port)
+{
+	struct pic32_sport *sport = to_pic32_sport(port);
+
+	pic32_uart_irqtxen(sport, 1);
+	pic32_uart_rset(PIC32_UART_STA_UTXEN, sport, PIC32_UART_STA);
+}
+
+/* serial core request to stop rx, called before port shutdown */
+static void pic32_uart_stop_rx(struct uart_port *port)
+{
+	struct pic32_sport *sport = to_pic32_sport(port);
+
+	/* disable rx interrupts */
+	disable_irq(sport->irq_rx);
+
+	/* receiver Enable bit OFF */
+	pic32_uart_rclr(PIC32_UART_STA_URXEN, sport, PIC32_UART_STA);
+}
+
+/* serial core request to start/stop emitting break char */
+static void pic32_uart_break_ctl(struct uart_port *port, int ctl)
+{
+	struct pic32_sport *sport = to_pic32_sport(port);
+	unsigned long flags = 0;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	if (ctl)
+		pic32_uart_rset(PIC32_UART_STA_UTXBRK, sport, PIC32_UART_STA);
+	else
+		pic32_uart_rclr(PIC32_UART_STA_UTXBRK, sport, PIC32_UART_STA);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/* get port type in string format */
+static const char *pic32_uart_type(struct uart_port *port)
+{
+	return (port->type == PORT_PIC32) ? PIC32_DEV_NAME : NULL;
+}
+
+/* read all chars in rx fifo and send them to core */
+static void pic32_uart_do_rx(struct uart_port *port)
+{
+	struct pic32_sport *sport = to_pic32_sport(port);
+	struct tty_port *tty;
+	unsigned int max_count;
+
+	/* limit number of char read in interrupt, should not be
+	 * higher than fifo size anyway since we're much faster than
+	 * serial port
+	 */
+	max_count = PIC32_UART_RX_FIFO_DEPTH;
+
+	spin_lock(&port->lock);
+
+	tty = &port->state->port;
+
+	do {
+		u32 sta_reg, c;
+		char flag;
+
+		/* get overrun/fifo empty information from status register */
+		sta_reg = pic32_uart_read(sport, PIC32_UART_STA);
+		if (unlikely(sta_reg & PIC32_UART_STA_OERR)) {
+
+			/* fifo reset is required to clear interrupt */
+			pic32_uart_rclr(PIC32_UART_STA_OERR, sport,
+							PIC32_UART_STA);
+
+			port->icount.overrun++;
+			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+		}
+
+		/* Can at least one more character can be read? */
+		if (!(sta_reg & PIC32_UART_STA_URXDA))
+			break;
+
+		/* read the character and increment the rx counter */
+		c = pic32_uart_read(sport, PIC32_UART_RX);
+
+		port->icount.rx++;
+		flag = TTY_NORMAL;
+		c &= 0xff;
+
+		if (unlikely((sta_reg & PIC32_UART_STA_PERR) ||
+			     (sta_reg & PIC32_UART_STA_FERR))) {
+
+			/* do stats first */
+			if (sta_reg & PIC32_UART_STA_PERR)
+				port->icount.parity++;
+			if (sta_reg & PIC32_UART_STA_FERR)
+				port->icount.frame++;
+
+			/* update flag wrt read_status_mask */
+			sta_reg &= port->read_status_mask;
+
+			if (sta_reg & PIC32_UART_STA_FERR)
+				flag = TTY_FRAME;
+			if (sta_reg & PIC32_UART_STA_PERR)
+				flag = TTY_PARITY;
+		}
+
+		if (uart_handle_sysrq_char(port, c))
+			continue;
+
+		if ((sta_reg & port->ignore_status_mask) == 0)
+			tty_insert_flip_char(tty, c, flag);
+
+	} while (--max_count);
+
+	spin_unlock(&port->lock);
+
+	tty_flip_buffer_push(tty);
+}
+
+/* fill tx fifo with chars to send, stop when fifo is about to be full
+ * or when all chars have been sent.
+ */
+static void pic32_uart_do_tx(struct uart_port *port)
+{
+	struct pic32_sport *sport = to_pic32_sport(port);
+	struct circ_buf *xmit = &port->state->xmit;
+	unsigned int max_count = PIC32_UART_TX_FIFO_DEPTH;
+
+	if (port->x_char) {
+		pic32_uart_write(port->x_char, sport, PIC32_UART_TX);
+		port->icount.tx++;
+		port->x_char = 0;
+		return;
+	}
+
+	if (uart_tx_stopped(port)) {
+		pic32_uart_stop_tx(port);
+		return;
+	}
+
+	if (uart_circ_empty(xmit))
+		goto txq_empty;
+
+	/* keep stuffing chars into uart tx buffer
+	 * 1) until uart fifo is full
+	 * or
+	 * 2) until the circ buffer is empty
+	 * (all chars have been sent)
+	 * or
+	 * 3) until the max count is reached
+	 * (prevents lingering here for too long in certain cases)
+	 */
+	while (!(PIC32_UART_STA_UTXBF &
+		pic32_uart_rval(sport, PIC32_UART_STA))) {
+		unsigned int c = xmit->buf[xmit->tail];
+
+		pic32_uart_write(c, sport, PIC32_UART_TX);
+
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		port->icount.tx++;
+		--max_count;
+		if (uart_circ_empty(xmit))
+			break;
+		if (max_count == 0)
+			break;
+	}
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+
+	if (uart_circ_empty(xmit))
+		goto txq_empty;
+
+	return;
+
+txq_empty:
+	pic32_uart_irqtxen(sport, 0);
+}
+
+/* RX interrupt handler */
+static irqreturn_t pic32_uart_rx_interrupt(int irq, void *dev_id)
+{
+	struct uart_port *port = dev_id;
+
+	pic32_uart_do_rx(port);
+
+	return IRQ_HANDLED;
+}
+
+/* TX interrupt handler */
+static irqreturn_t pic32_uart_tx_interrupt(int irq, void *dev_id)
+{
+	struct uart_port *port = dev_id;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+	pic32_uart_do_tx(port);
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+/* FAULT interrupt handler */
+static irqreturn_t pic32_uart_fault_interrupt(int irq, void *dev_id)
+{
+	/* do nothing: pic32_uart_do_rx() handles faults. */
+	return IRQ_HANDLED;
+}
+
+/* enable rx & tx operation on uart */
+static void pic32_uart_en_and_unmask(struct uart_port *port)
+{
+	struct pic32_sport *sport = to_pic32_sport(port);
+
+	pic32_uart_rset(PIC32_UART_STA_UTXEN | PIC32_UART_STA_URXEN,
+			sport, PIC32_UART_STA);
+	pic32_uart_rset(PIC32_UART_MODE_ON, sport, PIC32_UART_MODE);
+}
+
+/* disable rx & tx operation on uart */
+static void pic32_uart_dsbl_and_mask(struct uart_port *port)
+{
+	struct pic32_sport *sport = to_pic32_sport(port);
+
+	pic32_uart_rclr(PIC32_UART_MODE_ON, sport, PIC32_UART_MODE);
+	pic32_uart_rclr(PIC32_UART_STA_UTXEN | PIC32_UART_STA_URXEN,
+			sport, PIC32_UART_STA);
+}
+
+/* serial core request to initialize uart and start rx operation */
+static int pic32_uart_startup(struct uart_port *port)
+{
+	struct pic32_sport *sport = to_pic32_sport(port);
+	u32 dflt_baud = ((port->uartclk / PIC32_UART_DFLT_BRATE) / 16) - 1;
+	unsigned long flags;
+	int ret = 0;
+
+	local_irq_save(flags);
+
+	ret = pic32_enable_clock(sport);
+	if (ret)
+		goto out_unlock;
+
+	/* clear status and mode registers */
+	pic32_uart_write(0, sport, PIC32_UART_MODE);
+	pic32_uart_write(0, sport, PIC32_UART_STA);
+
+	/* disable uart and mask all interrupts */
+	pic32_uart_dsbl_and_mask(port);
+
+	/* set default baud */
+	pic32_uart_write(dflt_baud, sport, PIC32_UART_BRG);
+
+	local_irq_restore(flags);
+
+	/* Each UART of a PIC32 has three interrupts therefore,
+	 * we setup driver to register the 3 irqs for the device.
+	 *
+	 * For each irq request_irq() is called with interrupt disabled.
+	 * And the irq is enabled as soon as we are ready to handle them.
+	 */
+	tx_irq_enabled(sport) = 0;
+
+	sport->irq_fault_name = kasprintf(GFP_KERNEL, "%s%d-fault",
+					  pic32_uart_type(port),
+					  sport->idx);
+	irq_set_status_flags(sport->irq_fault, IRQ_NOAUTOEN);
+	ret = request_irq(sport->irq_fault, pic32_uart_fault_interrupt,
+			  sport->irqflags_fault, sport->irq_fault_name, port);
+	if (ret) {
+		dev_err(port->dev, "%s: request irq(%d) err! ret:%d name:%s\n",
+			__func__, sport->irq_fault, ret,
+			pic32_uart_type(port));
+		goto out_done;
+	}
+
+	sport->irq_rx_name = kasprintf(GFP_KERNEL, "%s%d-rx",
+				       pic32_uart_type(port),
+				       sport->idx);
+	irq_set_status_flags(sport->irq_rx, IRQ_NOAUTOEN);
+	ret = request_irq(sport->irq_rx, pic32_uart_rx_interrupt,
+			  sport->irqflags_rx, sport->irq_rx_name, port);
+	if (ret) {
+		dev_err(port->dev, "%s: request irq(%d) err! ret:%d name:%s\n",
+			__func__, sport->irq_rx, ret,
+			pic32_uart_type(port));
+		goto out_done;
+	}
+
+	sport->irq_tx_name = kasprintf(GFP_KERNEL, "%s%d-tx",
+				       pic32_uart_type(port),
+				       sport->idx);
+	irq_set_status_flags(sport->irq_tx, IRQ_NOAUTOEN);
+	ret = request_irq(sport->irq_tx, pic32_uart_tx_interrupt,
+			  sport->irqflags_tx, sport->irq_tx_name, port);
+	if (ret) {
+		dev_err(port->dev, "%s: request irq(%d) err! ret:%d name:%s\n",
+			__func__, sport->irq_tx, ret,
+			pic32_uart_type(port));
+		goto out_done;
+	}
+
+	local_irq_save(flags);
+
+	/* set rx interrupt on first receive */
+	pic32_uart_rclr(PIC32_UART_STA_URXISEL1 | PIC32_UART_STA_URXISEL0,
+							sport, PIC32_UART_STA);
+
+	/* set interrupt on empty */
+	pic32_uart_rclr(PIC32_UART_STA_UTXISEL1, sport, PIC32_UART_STA);
+
+	/* enable all interrupts and eanable uart */
+	pic32_uart_en_and_unmask(port);
+
+	enable_irq(sport->irq_fault);
+	enable_irq(sport->irq_rx);
+
+out_unlock:
+	local_irq_restore(flags);
+
+out_done:
+	return ret;
+}
+
+/* serial core request to flush & disable uart */
+static void pic32_uart_shutdown(struct uart_port *port)
+{
+	struct pic32_sport *sport = to_pic32_sport(port);
+	unsigned long flags;
+
+	/* disable uart */
+	spin_lock_irqsave(&port->lock, flags);
+	pic32_uart_dsbl_and_mask(port);
+	spin_unlock_irqrestore(&port->lock, flags);
+	pic32_disable_clock(sport);
+
+	/* free all 3 interrupts for this UART */
+	free_irq(sport->irq_fault, port);
+	free_irq(sport->irq_tx, port);
+	free_irq(sport->irq_rx, port);
+}
+
+/* serial core request to change current uart setting */
+static void pic32_uart_set_termios(struct uart_port *port,
+				   struct ktermios *new,
+				   struct ktermios *old)
+{
+	struct pic32_sport *sport = to_pic32_sport(port);
+	unsigned int baud;
+	unsigned int quot;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	/* disable uart and mask all interrupts while changing speed */
+	pic32_uart_dsbl_and_mask(port);
+
+	/* stop bit options */
+	if (new->c_cflag & CSTOPB)
+		pic32_uart_rset(PIC32_UART_MODE_STSEL, sport, PIC32_UART_MODE);
+	else
+		pic32_uart_rclr(PIC32_UART_MODE_STSEL, sport, PIC32_UART_MODE);
+
+	/* parity options */
+	if (new->c_cflag & PARENB) {
+		if (new->c_cflag & PARODD) {
+			pic32_uart_rset(PIC32_UART_MODE_PDSEL1, sport,
+					PIC32_UART_MODE);
+			pic32_uart_rclr(PIC32_UART_MODE_PDSEL0, sport,
+					PIC32_UART_MODE);
+		} else {
+			pic32_uart_rset(PIC32_UART_MODE_PDSEL0, sport,
+					PIC32_UART_MODE);
+			pic32_uart_rclr(PIC32_UART_MODE_PDSEL1, sport,
+					PIC32_UART_MODE);
+		}
+	} else {
+		pic32_uart_rclr(PIC32_UART_MODE_PDSEL1 | PIC32_UART_MODE_PDSEL0,
+				sport, PIC32_UART_MODE);
+	}
+	/* if hw flow ctrl, then the pins must be specified in device tree */
+	if ((new->c_cflag & CRTSCTS) && sport->hw_flow_ctrl) {
+		/* enable hardware flow control */
+		pic32_uart_rset(PIC32_UART_MODE_UEN1, sport, PIC32_UART_MODE);
+		pic32_uart_rclr(PIC32_UART_MODE_UEN0, sport, PIC32_UART_MODE);
+		pic32_uart_rclr(PIC32_UART_MODE_RTSMD, sport, PIC32_UART_MODE);
+	} else {
+		/* disable hardware flow control */
+		pic32_uart_rclr(PIC32_UART_MODE_UEN1, sport, PIC32_UART_MODE);
+		pic32_uart_rclr(PIC32_UART_MODE_UEN0, sport, PIC32_UART_MODE);
+		pic32_uart_rclr(PIC32_UART_MODE_RTSMD, sport, PIC32_UART_MODE);
+	}
+
+	/* update baud */
+	baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16);
+	quot = uart_get_divisor(port, baud) - 1;
+	pic32_uart_write(quot, sport, PIC32_UART_BRG);
+	uart_update_timeout(port, new->c_cflag, baud);
+
+	/* enable uart */
+	pic32_uart_en_and_unmask(port);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/* serial core request to claim uart iomem */
+static int pic32_uart_request_port(struct uart_port *port)
+{
+	struct platform_device *pdev = to_platform_device(port->dev);
+	struct resource *res_mem;
+	unsigned int res_size;
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (unlikely(!res_mem))
+		return -EINVAL;
+	res_size = resource_size(res_mem);
+
+	if (!request_mem_region(port->mapbase, res_size, "pic32_uart_mem")) {
+		dev_err(port->dev, "Memory region busy\n");
+		return -EBUSY;
+	}
+
+	port->membase = devm_ioremap_nocache(port->dev,
+					     port->mapbase, res_size);
+	if (!port->membase) {
+		dev_err(port->dev, "Unable to map registers\n");
+		release_mem_region(port->mapbase, res_size);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/* serial core request to release uart iomem */
+static void pic32_uart_release_port(struct uart_port *port)
+{
+	struct platform_device *pdev = to_platform_device(port->dev);
+	struct resource *res_mem;
+	unsigned int res_size;
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (unlikely(!res_mem))
+		return;
+	res_size = resource_size(res_mem);
+
+	release_mem_region(port->mapbase, res_size);
+	devm_iounmap(port->dev, port->membase);
+}
+
+/* serial core request to do any port required auto-configuration */
+static void pic32_uart_config_port(struct uart_port *port, int flags)
+{
+	if (flags & UART_CONFIG_TYPE) {
+		if (pic32_uart_request_port(port))
+			return;
+		port->type = PORT_PIC32;
+	}
+}
+
+/* serial core request to check that port information in serinfo are suitable */
+static int pic32_uart_verify_port(struct uart_port *port,
+				  struct serial_struct *serinfo)
+{
+	if (port->type != PORT_PIC32)
+		return -EINVAL;
+	if (port->irq != serinfo->irq)
+		return -EINVAL;
+	if (port->iotype != serinfo->io_type)
+		return -EINVAL;
+	if (port->mapbase != (unsigned long)serinfo->iomem_base)
+		return -EINVAL;
+
+	return 0;
+}
+
+/* serial core callbacks */
+static const struct uart_ops pic32_uart_ops = {
+	.tx_empty	= pic32_uart_tx_empty,
+	.get_mctrl	= pic32_uart_get_mctrl,
+	.set_mctrl	= pic32_uart_set_mctrl,
+	.start_tx	= pic32_uart_start_tx,
+	.stop_tx	= pic32_uart_stop_tx,
+	.stop_rx	= pic32_uart_stop_rx,
+	.break_ctl	= pic32_uart_break_ctl,
+	.startup	= pic32_uart_startup,
+	.shutdown	= pic32_uart_shutdown,
+	.set_termios	= pic32_uart_set_termios,
+	.type		= pic32_uart_type,
+	.release_port	= pic32_uart_release_port,
+	.request_port	= pic32_uart_request_port,
+	.config_port	= pic32_uart_config_port,
+	.verify_port	= pic32_uart_verify_port,
+};
+
+#ifdef CONFIG_SERIAL_PIC32_CONSOLE
+/* output given char */
+static void pic32_console_putchar(struct uart_port *port, int ch)
+{
+	struct pic32_sport *sport = to_pic32_sport(port);
+
+	if (!(pic32_uart_read(sport, PIC32_UART_MODE) & PIC32_UART_MODE_ON))
+		return;
+
+	if (!(pic32_uart_read(sport, PIC32_UART_STA) & PIC32_UART_STA_UTXEN))
+		return;
+
+	/* wait for tx empty */
+	while (!(pic32_uart_read(sport, PIC32_UART_STA) & PIC32_UART_STA_TRMT))
+		udelay(1);
+
+	pic32_uart_write(ch & 0xff, sport, PIC32_UART_TX);
+}
+
+/* console core request to output given string */
+static void pic32_console_write(struct console *co, const char *s,
+				unsigned int count)
+{
+	struct pic32_sport *sport = pic32_sports[co->index];
+	struct uart_port *port = pic32_get_port(sport);
+
+	/* call uart helper to deal with \r\n */
+	uart_console_write(port, s, count, pic32_console_putchar);
+}
+
+/* console core request to setup given console, find matching uart
+ * port and setup it.
+ */
+static int pic32_console_setup(struct console *co, char *options)
+{
+	struct pic32_sport *sport;
+	struct uart_port *port = NULL;
+	int baud = 115200;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+	int ret = 0;
+
+	if (unlikely(co->index < 0 || co->index >= PIC32_MAX_UARTS))
+		return -ENODEV;
+
+	sport = pic32_sports[co->index];
+	if (!sport)
+		return -ENODEV;
+	port = pic32_get_port(sport);
+
+	ret = pic32_enable_clock(sport);
+	if (ret)
+		return ret;
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver pic32_uart_driver;
+static struct console pic32_console = {
+	.name		= PIC32_SDEV_NAME,
+	.write		= pic32_console_write,
+	.device		= uart_console_device,
+	.setup		= pic32_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+	.data		= &pic32_uart_driver,
+};
+#define PIC32_SCONSOLE (&pic32_console)
+
+static int __init pic32_console_init(void)
+{
+	register_console(&pic32_console);
+	return 0;
+}
+console_initcall(pic32_console_init);
+
+static inline bool is_pic32_console_port(struct uart_port *port)
+{
+	return (port->cons && port->cons->index == port->line);
+}
+
+/*
+ * Late console initialization.
+ */
+static int __init pic32_late_console_init(void)
+{
+	if (!(pic32_console.flags & CON_ENABLED))
+		register_console(&pic32_console);
+
+	return 0;
+}
+
+core_initcall(pic32_late_console_init);
+
+#else
+#define PIC32_SCONSOLE NULL
+#endif
+
+static struct uart_driver pic32_uart_driver = {
+	.owner			= THIS_MODULE,
+	.driver_name		= PIC32_DEV_NAME,
+	.dev_name		= PIC32_SDEV_NAME,
+	.major			= PIC32_SDEV_MAJOR,
+	.minor			= PIC32_SDEV_MINOR,
+	.nr			= PIC32_MAX_UARTS,
+	.cons			= PIC32_SCONSOLE,
+};
+
+static int pic32_uart_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct pic32_sport *sport;
+	int uart_idx = 0;
+	struct resource *res_mem;
+	struct uart_port *port;
+	int ret = 0;
+
+	uart_idx = of_alias_get_id(np, "serial");
+	if (uart_idx < 0 || uart_idx >= PIC32_MAX_UARTS)
+		return -EINVAL;
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res_mem)
+		return -EINVAL;
+
+	sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
+	if (!sport)
+		return -ENOMEM;
+
+	sport->idx		= uart_idx;
+	sport->irq_fault	= irq_of_parse_and_map(np, 0);
+	sport->irqflags_fault	= IRQF_NO_THREAD;
+	sport->irq_rx		= irq_of_parse_and_map(np, 1);
+	sport->irqflags_rx	= IRQF_NO_THREAD;
+	sport->irq_tx		= irq_of_parse_and_map(np, 2);
+	sport->irqflags_tx	= IRQF_NO_THREAD;
+	sport->clk		= devm_clk_get(&pdev->dev, NULL);
+	sport->cts_gpio		= -EINVAL;
+	sport->dev		= &pdev->dev;
+
+	ret = pic32_enable_clock(sport);
+	if (ret) {
+		dev_err(&pdev->dev, "clk enable ?\n");
+		goto err;
+	}
+
+	/* Hardware flow control: gpios
+	 * !Note: Basically, CTS is needed for reading the status.
+	 */
+	sport->hw_flow_ctrl = false;
+	sport->cts_gpio = of_get_named_gpio(np, "cts-gpios", 0);
+	if (gpio_is_valid(sport->cts_gpio)) {
+		sport->hw_flow_ctrl = true;
+
+		ret = devm_gpio_request(sport->dev,
+					sport->cts_gpio, "CTS");
+		if (ret) {
+			dev_err(&pdev->dev,
+				"error requesting CTS GPIO\n");
+			goto err_disable_clk;
+		}
+
+		ret = gpio_direction_input(sport->cts_gpio);
+		if (ret) {
+			dev_err(&pdev->dev, "error setting CTS GPIO\n");
+			goto err_disable_clk;
+		}
+	}
+
+	pic32_sports[uart_idx] = sport;
+	port = &sport->port;
+	memset(port, 0, sizeof(*port));
+	port->iotype	= UPIO_MEM;
+	port->mapbase	= res_mem->start;
+	port->ops	= &pic32_uart_ops;
+	port->flags	= UPF_BOOT_AUTOCONF;
+	port->dev	= &pdev->dev;
+	port->fifosize	= PIC32_UART_TX_FIFO_DEPTH;
+	port->uartclk	= clk_get_rate(sport->clk);
+	port->line	= uart_idx;
+
+	ret = uart_add_one_port(&pic32_uart_driver, port);
+	if (ret) {
+		port->membase = NULL;
+		dev_err(port->dev, "%s: uart add port error!\n", __func__);
+		goto err_disable_clk;
+	}
+
+#ifdef CONFIG_SERIAL_PIC32_CONSOLE
+	if (is_pic32_console_port(port) &&
+	    (pic32_console.flags & CON_ENABLED)) {
+		/* The peripheral clock has been enabled by console_setup,
+		 * so disable it till the port is used.
+		 */
+		pic32_disable_clock(sport);
+	}
+#endif
+
+	platform_set_drvdata(pdev, port);
+
+	dev_info(&pdev->dev, "%s: uart(%d) driver initialized.\n",
+		 __func__, uart_idx);
+	ret = 0;
+
+err_disable_clk:
+	/* disable clock till the port is used. */
+	pic32_disable_clock(sport);
+err:
+	/* automatic unroll of sport and gpios */
+	return ret;
+}
+
+static int pic32_uart_remove(struct platform_device *pdev)
+{
+	struct uart_port *port = platform_get_drvdata(pdev);
+	struct pic32_sport *sport = to_pic32_sport(port);
+
+	uart_remove_one_port(&pic32_uart_driver, port);
+	pic32_disable_clock(sport);
+	platform_set_drvdata(pdev, NULL);
+	pic32_sports[sport->idx] = NULL;
+
+	/* automatic unroll of sport and gpios */
+	return 0;
+}
+
+static const struct of_device_id pic32_serial_dt_ids[] = {
+	{ .compatible = "microchip,pic32mzda-uart" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, pic32_serial_dt_ids);
+
+static struct platform_driver pic32_uart_platform_driver = {
+	.probe		= pic32_uart_probe,
+	.remove		= pic32_uart_remove,
+	.driver		= {
+		.name	= PIC32_DEV_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table	= of_match_ptr(pic32_serial_dt_ids),
+	},
+};
+
+static int __init pic32_uart_init(void)
+{
+	int ret;
+
+	ret = uart_register_driver(&pic32_uart_driver);
+	if (ret) {
+		pr_err("failed to register %s:%d\n",
+		       pic32_uart_driver.driver_name, ret);
+		return ret;
+	}
+
+	ret = platform_driver_register(&pic32_uart_platform_driver);
+	if (ret) {
+		pr_err("fail to register pic32 uart\n");
+		uart_unregister_driver(&pic32_uart_driver);
+	}
+
+	return ret;
+}
+arch_initcall(pic32_uart_init);
+
+static void __exit pic32_uart_exit(void)
+{
+#ifdef CONFIG_SERIAL_PIC32_CONSOLE
+	unregister_console(&pic32_console);
+#endif
+	platform_driver_unregister(&pic32_uart_platform_driver);
+	uart_unregister_driver(&pic32_uart_driver);
+}
+module_exit(pic32_uart_exit);
+
+MODULE_AUTHOR("Steve Scott <steve.scott@microchip.com>");
+MODULE_DESCRIPTION("Microchip PIC32 integrated serial port driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/tty/serial/pic32_uart.h b/drivers/tty/serial/pic32_uart.h
new file mode 100644
index 0000000..b2f6960
--- /dev/null
+++ b/drivers/tty/serial/pic32_uart.h
@@ -0,0 +1,198 @@
+/*
+ * PIC32 Integrated Serial Driver.
+ *
+ * Copyright (C) 2015 Microchip Technology, Inc.
+ *
+ * Authors:
+ *   Sorin-Andrei Pistirica <andrei.pistirica@microchip.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+#ifndef __DT_PIC32_UART_H__
+#define __DT_PIC32_UART_H__
+
+#define PIC32_UART_DFLT_BRATE		(9600)
+#define PIC32_UART_TX_FIFO_DEPTH	(8)
+#define PIC32_UART_RX_FIFO_DEPTH	(8)
+
+struct pic32_console_opt {
+	int baud;
+	int parity;
+	int bits;
+	int flow;
+};
+/* struct pic32_sport - pic32 serial port descriptor
+ * @port: uart port descriptor
+ * @idx: port index
+ * @irq_fault: virtual fault interrupt number
+ * @irqflags_fault: flags related to fault irq
+ * @irq_fault_name: irq fault name
+ * @irq_rx: virtual rx interrupt number
+ * @irqflags_rx: flags related to rx irq
+ * @irq_rx_name: irq rx name
+ * @irq_tx: virtual tx interrupt number
+ * @irqflags_tx: : flags related to tx irq
+ * @irq_tx_name: irq tx name
+ * @cts_gpio: clear to send gpio
+ * @dev: device descriptor
+ **/
+struct pic32_sport {
+	struct uart_port port;
+	struct pic32_console_opt opt;
+	int idx;
+
+	int irq_fault;
+	int irqflags_fault;
+	const char *irq_fault_name;
+	int irq_rx;
+	int irqflags_rx;
+	const char *irq_rx_name;
+	int irq_tx;
+	int irqflags_tx;
+	const char *irq_tx_name;
+	u8 enable_tx_irq;
+
+	bool hw_flow_ctrl;
+	int cts_gpio;
+
+	int ref_clk;
+	struct clk *clk;
+
+	struct device *dev;
+};
+#define to_pic32_sport(c) container_of(c, struct pic32_sport, port)
+#define pic32_get_port(sport) (&sport->port)
+#define pic32_get_opt(sport) (&sport->opt)
+#define tx_irq_enabled(sport) (sport->enable_tx_irq)
+
+struct pic32_reg {
+	u32 val;
+	u32 clr;
+	u32 set;
+	u32 inv;
+} __packed;
+#define PIC32_REGS 4
+#define PIC32_REG_SIZE 4
+
+enum pic32_uart_regs {
+	PIC32_UART_UNKNOWN	= 0,
+	PIC32_UART_MODE		= 1,
+	PIC32_UART_STA		= 2,
+	PIC32_UART_TX		= 3,
+	PIC32_UART_RX		= 4,
+	PIC32_UART_BRG		= 5,
+
+	/* add above this line */
+	PIC32_UART_LAST
+};
+
+/* uart register offsets */
+static u32 pic32_uart_lookup_reg[PIC32_UART_LAST] = {
+	[PIC32_UART_MODE]	= 0 * PIC32_REGS * PIC32_REG_SIZE,
+	[PIC32_UART_STA]	= 1 * PIC32_REGS * PIC32_REG_SIZE,
+	[PIC32_UART_TX]		= 2 * PIC32_REGS * PIC32_REG_SIZE,
+	[PIC32_UART_RX]		= 3 * PIC32_REGS * PIC32_REG_SIZE,
+	[PIC32_UART_BRG]	= 4 * PIC32_REGS * PIC32_REG_SIZE,
+};
+
+static inline void __iomem *pic32_uart_get_reg(struct pic32_sport *sport,
+					       enum pic32_uart_regs reg)
+{
+	struct uart_port *port = pic32_get_port(sport);
+
+	return port->membase + pic32_uart_lookup_reg[reg];
+}
+
+static inline u32 pic32_uart_rval(struct pic32_sport *sport,
+				  enum pic32_uart_regs reg)
+{
+	void __iomem *addr = pic32_uart_get_reg(sport, reg);
+	struct pic32_reg __iomem *reg_addr = (struct pic32_reg __iomem *)addr;
+
+	return readl(&reg_addr->val);
+}
+
+static inline void pic32_uart_rset(u32 val,
+				   struct pic32_sport *sport,
+				   enum pic32_uart_regs reg)
+{
+	void __iomem *addr = pic32_uart_get_reg(sport, reg);
+	struct pic32_reg __iomem *reg_addr = (struct pic32_reg __iomem *)addr;
+
+	writel(val, &reg_addr->set);
+}
+
+static inline void pic32_uart_rclr(u32 val,
+				   struct pic32_sport *sport,
+				   enum pic32_uart_regs reg)
+{
+	void __iomem *addr = pic32_uart_get_reg(sport, reg);
+	struct pic32_reg __iomem *reg_addr = (struct pic32_reg __iomem *)addr;
+
+	writel(val, &reg_addr->clr);
+}
+
+static inline void pic32_uart_rinv(u32 val,
+				   struct pic32_sport *sport,
+				   enum pic32_uart_regs reg)
+{
+	void __iomem *addr = pic32_uart_get_reg(sport, reg);
+	struct pic32_reg __iomem *reg_addr = (struct pic32_reg __iomem *)addr;
+
+	writel(val, &reg_addr->inv);
+}
+
+static inline void pic32_uart_write(u32 val,
+				    struct pic32_sport *sport,
+				    enum pic32_uart_regs reg)
+{
+	void __iomem *addr = pic32_uart_get_reg(sport, reg);
+
+	writel(val, addr);
+}
+
+static inline u32 pic32_uart_read(struct pic32_sport *sport,
+				  enum pic32_uart_regs reg)
+{
+	void __iomem *addr = pic32_uart_get_reg(sport, reg);
+
+	return readl(addr);
+}
+
+/* pic32 uart mode register bits */
+#define PIC32_UART_MODE_ON        (1 << 15)
+#define PIC32_UART_MODE_FRZ       (1 << 14)
+#define PIC32_UART_MODE_SIDL      (1 << 13)
+#define PIC32_UART_MODE_IREN      (1 << 12)
+#define PIC32_UART_MODE_RTSMD     (1 << 11)
+#define PIC32_UART_MODE_RESV1     (1 << 10)
+#define PIC32_UART_MODE_UEN1      (1 << 9)
+#define PIC32_UART_MODE_UEN0      (1 << 8)
+#define PIC32_UART_MODE_WAKE      (1 << 7)
+#define PIC32_UART_MODE_LPBK      (1 << 6)
+#define PIC32_UART_MODE_ABAUD     (1 << 5)
+#define PIC32_UART_MODE_RXINV     (1 << 4)
+#define PIC32_UART_MODE_BRGH      (1 << 3)
+#define PIC32_UART_MODE_PDSEL1    (1 << 2)
+#define PIC32_UART_MODE_PDSEL0    (1 << 1)
+#define PIC32_UART_MODE_STSEL     (1 << 0)
+
+/* pic32 uart status register bits */
+#define PIC32_UART_STA_UTXISEL1   (1 << 15)
+#define PIC32_UART_STA_UTXISEL0   (1 << 14)
+#define PIC32_UART_STA_UTXINV     (1 << 13)
+#define PIC32_UART_STA_URXEN      (1 << 12)
+#define PIC32_UART_STA_UTXBRK     (1 << 11)
+#define PIC32_UART_STA_UTXEN      (1 << 10)
+#define PIC32_UART_STA_UTXBF      (1 << 9)
+#define PIC32_UART_STA_TRMT       (1 << 8)
+#define PIC32_UART_STA_URXISEL1   (1 << 7)
+#define PIC32_UART_STA_URXISEL0   (1 << 6)
+#define PIC32_UART_STA_ADDEN      (1 << 5)
+#define PIC32_UART_STA_RIDLE      (1 << 4)
+#define PIC32_UART_STA_PERR       (1 << 3)
+#define PIC32_UART_STA_FERR       (1 << 2)
+#define PIC32_UART_STA_OERR       (1 << 1)
+#define PIC32_UART_STA_URXDA      (1 << 0)
+
+#endif /* __DT_PIC32_UART_H__ */
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index 93ba148..9df0a98 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -261,4 +261,7 @@
 /* STM32 USART */
 #define PORT_STM32	113
 
+/* Microchip PIC32 UART */
+#define PORT_PIC32	114
+
 #endif /* _UAPILINUX_SERIAL_CORE_H */
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1291664 — [PATCH v2 14/14] MIPS: pic32mzda: Add initial PIC32MZDA Starter Kit defconfig

FromJoshua Henderson <joshua.henderson@microchip.com>
Date2015-12-14 23:50 +0100
Subject[PATCH v2 14/14] MIPS: pic32mzda: Add initial PIC32MZDA Starter Kit defconfig
Message-ID<qFK6n-3W4-53@gated-at.bofh.it>
In reply to#1291644
This adds an initial default config that enables all available PIC32
drivers and is enough for booting a PIC32MZDA Starter Kit.

Signed-off-by: Joshua Henderson <joshua.henderson@microchip.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
---
 arch/mips/configs/pic32mzda_defconfig |   88 +++++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)
 create mode 100644 arch/mips/configs/pic32mzda_defconfig

diff --git a/arch/mips/configs/pic32mzda_defconfig b/arch/mips/configs/pic32mzda_defconfig
new file mode 100644
index 0000000..17014ca
--- /dev/null
+++ b/arch/mips/configs/pic32mzda_defconfig
@@ -0,0 +1,88 @@
+CONFIG_MACH_PIC32=y
+CONFIG_DTB_PIC32_MZDA_SK=y
+CONFIG_HZ_100=y
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_SECCOMP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_RELAY=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLK_DEV_BSGLIB=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_SGI_PARTITION=y
+CONFIG_BINFMT_MISC=m
+# CONFIG_SUSPEND is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_ALLOW_DEV_COREDUMP is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_SCAN_ASYNC=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_INPUT_LEDS=m
+CONFIG_INPUT_POLLDEV=y
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=m
+CONFIG_KEYBOARD_GPIO_POLLED=m
+# CONFIG_MOUSE_PS2 is not set
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_PIC32=y
+CONFIG_SERIAL_PIC32_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_RAW_DRIVER=m
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_HIDRAW=y
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_MICROCHIP_PIC32=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_ONESHOT=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_GPIO=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+# CONFIG_MIPS_PLATFORM_DEVICES is not set
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+CONFIG_FSCACHE=m
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZ4=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web