All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v3 00/14] Initial Microchip PIC32MZ[DA] Support
@ 2016-01-12 10:18 Purna Chandra Mandal
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 01/14] MIPS: initialize board_init_f() argument to zero Purna Chandra Mandal
                   ` (13 more replies)
  0 siblings, 14 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-12 10:18 UTC (permalink / raw)
  To: u-boot

This patch series adds support for Microchip PIC32MZ[DA] MIPS microcontroller platform.
All drivers required to boot from MMC uSD card and network are included in it; clock,
pinctrl, gpio, DDR2, serial, SDHCI, ethernet.
This series is tested on PIC32MZ[DA] Starter Kit.

This series is generated on mips_io_v1 branch of u-boot-mips tree.
A tree with these changes are available at [2].

[2] https://github.com/purna-mandal/u-boot/tree/pic32-upstream-v3
[1] https://github.com/purna-mandal/u-boot/tree/pic32-upstream-v2
[0] https://github.com/purna-mandal/u-boot/tree/pic32-upstream-v1

Changes in v3:
- drop empty choices in mach-pic32/Kconfig
- add pic32_get_syscfg_base() for device-config regs base
- rename clk-pic32.c to clk_pic32.c
- update clock binding documentation
- replace pic32_ioremap() with ioremap()
- read register base from device-tree
- add/update comments to explain how pinctrl'r works.
- remove ofdata_to_platdata, and replace platdata with priv
- serial:remove special handling of '\r' as being handled by serial-uclass
- serial:remove loop to wait for space in tx buffer before pumping char
- pinctrl: annotating fixed table with const
- ddr: fix camel-case in ddr2 timing parameters
- ddr: fix cmd index parameter of host_load_cmd().
- drop forcing CONFIG_MIPS_BOOT_* selection in mach-pic32/Kconfig
- indent assembly instructions in delay slot
- made GPIO-nodes child of pinctrl-node in devicetree
- drop SKIP_LOWLEVEL_INIT, GBL_DATA_OFFSET from config header
- move CMD_MEMTEST, CMD_MEMINFO to defconfig
- increase SYS_MALLOC_F_LEN to 0x600
- use auto-generated defconfig - no hand edit
- net: merge internal wrappers functions with eth operation callbacks
- net: read ethernet-phy address from device-tree
- net: rename ethernet callback functions

Changes in v2:
- move PIC32 specific headers to arch/mips/mach-pic32/include/mach/
- define register-base as physical address
- drop CONFIG_PIC32_SUPPORTS_FDT_BOOT
- add mpll get clock rate
- add pinconf routine for configuring pin property
- fix missing/corrupted chars during baud rate change
- remove loop until any char is avaialbale in getc()
- move ddr2 initialization from board/microchip/ to drivers/ddr/microchip
- drop board_early_init_f
- use macro LEAF(), END() for lowlevel_init
- move initialization of board_init_f() argument to common start.S
- move initdram() from board/microchip/ to mach-pic32/cpu.c
- remove MIPS virtual address in favor physical one in dts file
- move CONFIG_SYS_TEXT_BASE (from board/*/config.mk) to include/configs/<board>.h
- drop sdhci shared bus configuration (for shared interrupt, clock pins)
- drop shared bus (shared pin selection) configuration.
- replace unbounded loop with wait_for_bit()
- replace register access as readl/writel(base + offset)
- translate (dts provided) physical address to MIPS kseg1 address before use

Andrei Pistirica (1):
  drivers: mmc: add driver for Microchip PIC32 SDHCI controller.

Paul Thacker (1):
  drivers: serial: add driver for Microchip PIC32 UART controller.

Purna Chandra Mandal (12):
  MIPS: initialize board_init_f() argument to zero.
  MIPS: initial infrastructure for Microchip PIC32 architecture
  drivers: clk: Add clock driver for Microchip PIC32 Microcontroller.
  drivers: pinctrl: Add pinctrl driver for Microchip PIC32.
  drivers: gpio: add driver for Microchip PIC32 GPIO controller.
  drivers: ddr: Add DDR2 SDRAM controller driver for Microchip PIC32.
  MIPS: Add support for Microchip PIC32MZ[DA] SoC family.
  board: Add Microchip PIC32MZ[DA]-Starter-Kit board.
  board: add SDHCI support for PIC32MZDASK board.
  drivers: net: phy: add SMSC LAN8740 Phy support.
  drivers: net: Add ethernet driver for Microchip PIC32.
  board: Enable ethernet, tftpboot support to pic32mzdask board.

 arch/mips/Kconfig                                  |   6 +
 arch/mips/Makefile                                 |   1 +
 arch/mips/cpu/start.S                              |   2 +
 arch/mips/dts/Makefile                             |   2 +-
 arch/mips/dts/pic32mzda.dtsi                       | 174 ++++++
 arch/mips/dts/pic32mzda_sk.dts                     |  55 ++
 arch/mips/mach-pic32/Kconfig                       |  38 ++
 arch/mips/mach-pic32/Makefile                      |   7 +
 arch/mips/mach-pic32/cpu.c                         | 160 ++++++
 arch/mips/mach-pic32/include/mach/ddr.h            |  32 ++
 arch/mips/mach-pic32/include/mach/pic32.h          |  79 +++
 arch/mips/mach-pic32/lowlevel_init.S               |  27 +
 arch/mips/mach-pic32/reset.c                       |  36 ++
 board/microchip/pic32mzda/Kconfig                  |  13 +
 board/microchip/pic32mzda/MAINTAINERS              |   6 +
 board/microchip/pic32mzda/Makefile                 |   7 +
 board/microchip/pic32mzda/README                   |  22 +
 board/microchip/pic32mzda/pic32mzda.c              |  31 ++
 configs/pic32mzdask_defconfig                      | 426 +++++++++++++++
 .../clock/microchip,pic32-clock.txt                |  33 ++
 .../serial/microchip,pic32-uart.txt                |   5 +
 drivers/Makefile                                   |   1 +
 drivers/clk/Makefile                               |   1 +
 drivers/clk/clk_pic32.c                            | 433 +++++++++++++++
 drivers/ddr/microchip/Makefile                     |   6 +
 drivers/ddr/microchip/ddr2.c                       | 278 ++++++++++
 drivers/ddr/microchip/ddr2_regs.h                  | 148 +++++
 drivers/ddr/microchip/ddr2_timing.h                |  65 +++
 drivers/gpio/Kconfig                               |   7 +
 drivers/gpio/Makefile                              |   2 +-
 drivers/gpio/pic32_gpio.c                          | 175 ++++++
 drivers/mmc/Kconfig                                |   6 +
 drivers/mmc/Makefile                               |   2 +-
 drivers/mmc/pic32_sdhci.c                          |  61 +++
 drivers/mmc/sdhci.c                                |  12 +
 drivers/net/Kconfig                                |   7 +
 drivers/net/Makefile                               |   1 +
 drivers/net/phy/smsc.c                             |  10 +
 drivers/net/pic32_eth.c                            | 606 +++++++++++++++++++++
 drivers/net/pic32_eth.h                            | 171 ++++++
 drivers/net/pic32_mdio.c                           | 121 ++++
 drivers/pinctrl/Kconfig                            |   9 +
 drivers/pinctrl/Makefile                           |   1 +
 drivers/pinctrl/pinctrl_pic32.c                    | 363 ++++++++++++
 drivers/serial/Kconfig                             |  13 +
 drivers/serial/Makefile                            |   1 +
 drivers/serial/serial_pic32.c                      | 199 +++++++
 include/configs/pic32mzdask.h                      | 178 ++++++
 include/dt-bindings/clock/microchip,clock.h        |  29 +
 49 files changed, 4065 insertions(+), 3 deletions(-)
 create mode 100644 arch/mips/dts/pic32mzda.dtsi
 create mode 100644 arch/mips/dts/pic32mzda_sk.dts
 create mode 100644 arch/mips/mach-pic32/Kconfig
 create mode 100644 arch/mips/mach-pic32/Makefile
 create mode 100644 arch/mips/mach-pic32/cpu.c
 create mode 100644 arch/mips/mach-pic32/include/mach/ddr.h
 create mode 100644 arch/mips/mach-pic32/include/mach/pic32.h
 create mode 100644 arch/mips/mach-pic32/lowlevel_init.S
 create mode 100644 arch/mips/mach-pic32/reset.c
 create mode 100644 board/microchip/pic32mzda/Kconfig
 create mode 100644 board/microchip/pic32mzda/MAINTAINERS
 create mode 100644 board/microchip/pic32mzda/Makefile
 create mode 100644 board/microchip/pic32mzda/README
 create mode 100644 board/microchip/pic32mzda/pic32mzda.c
 create mode 100644 configs/pic32mzdask_defconfig
 create mode 100644 doc/device-tree-bindings/clock/microchip,pic32-clock.txt
 create mode 100644 doc/device-tree-bindings/serial/microchip,pic32-uart.txt
 create mode 100644 drivers/clk/clk_pic32.c
 create mode 100644 drivers/ddr/microchip/Makefile
 create mode 100644 drivers/ddr/microchip/ddr2.c
 create mode 100644 drivers/ddr/microchip/ddr2_regs.h
 create mode 100644 drivers/ddr/microchip/ddr2_timing.h
 create mode 100644 drivers/gpio/pic32_gpio.c
 create mode 100644 drivers/mmc/pic32_sdhci.c
 create mode 100644 drivers/net/pic32_eth.c
 create mode 100644 drivers/net/pic32_eth.h
 create mode 100644 drivers/net/pic32_mdio.c
 create mode 100644 drivers/pinctrl/pinctrl_pic32.c
 create mode 100644 drivers/serial/serial_pic32.c
 create mode 100644 include/configs/pic32mzdask.h
 create mode 100644 include/dt-bindings/clock/microchip,clock.h

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 01/14] MIPS: initialize board_init_f() argument to zero.
  2016-01-12 10:18 [U-Boot] [PATCH v3 00/14] Initial Microchip PIC32MZ[DA] Support Purna Chandra Mandal
@ 2016-01-12 10:18 ` Purna Chandra Mandal
  2016-01-12 12:29   ` Daniel Schwierzeck
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 02/14] MIPS: initial infrastructure for Microchip PIC32 architecture Purna Chandra Mandal
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-12 10:18 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
---

Changes in v3: None
Changes in v2: None

 arch/mips/cpu/start.S | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S
index e95cdca..35d9650 100644
--- a/arch/mips/cpu/start.S
+++ b/arch/mips/cpu/start.S
@@ -185,6 +185,8 @@ reset:
 	PTR_ADDU t0, k0, GD_MALLOC_BASE	# gd->malloc_base offset
 	sw	sp, 0(t0)
 #endif
+	/* Initialize args to zero */
+	move	a0, zero
 
 	PTR_LA	t9, board_init_f
 	jr	t9
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 02/14] MIPS: initial infrastructure for Microchip PIC32 architecture
  2016-01-12 10:18 [U-Boot] [PATCH v3 00/14] Initial Microchip PIC32MZ[DA] Support Purna Chandra Mandal
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 01/14] MIPS: initialize board_init_f() argument to zero Purna Chandra Mandal
@ 2016-01-12 10:18 ` Purna Chandra Mandal
  2016-01-12 12:55   ` Daniel Schwierzeck
  2016-01-13 14:56   ` Tom Rini
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 03/14] drivers: clk: Add clock driver for Microchip PIC32 Microcontroller Purna Chandra Mandal
                   ` (11 subsequent siblings)
  13 siblings, 2 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-12 10:18 UTC (permalink / raw)
  To: u-boot

Create initial directory, Kconfigs needed for PIC32 architecture
support. Also add PIC32 specific register definition required for drivers.

Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>

---

Changes in v3:
- drop empty choices in mach-pic32/Kconfig
- add pic32_get_syscfg_base() for device-config registers

Changes in v2:
- move PIC32 specific headers to arch/mips/mach-pic32/include/mach/
- define register-base as physical address
- drop CONFIG_PIC32_SUPPORTS_FDT_BOOT

 arch/mips/Kconfig                         |  6 +++
 arch/mips/Makefile                        |  1 +
 arch/mips/mach-pic32/Kconfig              |  7 +++
 arch/mips/mach-pic32/Makefile             |  7 +++
 arch/mips/mach-pic32/cpu.c                | 13 ++++++
 arch/mips/mach-pic32/include/mach/pic32.h | 76 +++++++++++++++++++++++++++++++
 6 files changed, 110 insertions(+)
 create mode 100644 arch/mips/mach-pic32/Kconfig
 create mode 100644 arch/mips/mach-pic32/Makefile
 create mode 100644 arch/mips/mach-pic32/cpu.c
 create mode 100644 arch/mips/mach-pic32/include/mach/pic32.h

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 1b39c4c..380ed81 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -54,6 +54,11 @@ config TARGET_PB1X00
 	select SYS_MIPS_CACHE_INIT_RAM_LOAD
 	select MIPS_TUNE_4KC
 
+config MACH_PIC32
+	bool "Support Microchip PIC32"
+	select OF_CONTROL
+	select DM
+
 endchoice
 
 source "board/dbau1x00/Kconfig"
@@ -61,6 +66,7 @@ source "board/imgtec/malta/Kconfig"
 source "board/micronas/vct/Kconfig"
 source "board/pb1x00/Kconfig"
 source "board/qemu-mips/Kconfig"
+source "arch/mips/mach-pic32/Kconfig"
 
 if MIPS
 
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 2133e7e..aec5a15 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -8,6 +8,7 @@ libs-y += arch/mips/cpu/
 libs-y += arch/mips/lib/
 
 machine-$(CONFIG_SOC_AU1X00) += au1x00
+machine-$(CONFIG_MACH_PIC32) += pic32
 
 machdirs := $(patsubst %,arch/mips/mach-%/,$(machine-y))
 libs-y += $(machdirs)
diff --git a/arch/mips/mach-pic32/Kconfig b/arch/mips/mach-pic32/Kconfig
new file mode 100644
index 0000000..c1cc5e3
--- /dev/null
+++ b/arch/mips/mach-pic32/Kconfig
@@ -0,0 +1,7 @@
+menu "Microchip PIC32 platforms"
+	depends on MACH_PIC32
+
+config SYS_SOC
+	default "none"
+
+endmenu
diff --git a/arch/mips/mach-pic32/Makefile b/arch/mips/mach-pic32/Makefile
new file mode 100644
index 0000000..cb42607
--- /dev/null
+++ b/arch/mips/mach-pic32/Makefile
@@ -0,0 +1,7 @@
+# (C) Copyright 2015
+# Purna Chandra Mandal, purna.mandal at microchip.com.
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+obj-y = cpu.o
diff --git a/arch/mips/mach-pic32/cpu.c b/arch/mips/mach-pic32/cpu.c
new file mode 100644
index 0000000..58fd3ab
--- /dev/null
+++ b/arch/mips/mach-pic32/cpu.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2015
+ * Purna Chandra Mandal <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ */
+#include <common.h>
+
+phys_size_t initdram(int board_type)
+{
+	return 0;
+}
diff --git a/arch/mips/mach-pic32/include/mach/pic32.h b/arch/mips/mach-pic32/include/mach/pic32.h
new file mode 100644
index 0000000..7e41810
--- /dev/null
+++ b/arch/mips/mach-pic32/include/mach/pic32.h
@@ -0,0 +1,76 @@
+/*
+ * (c) 2015 Paul Thacker <paul.thacker@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ */
+
+#ifndef __PIC32_REGS_H__
+#define __PIC32_REGS_H__
+
+#include <asm/io.h>
+
+/* System Configuration */
+#define PIC32_CFG_BASE		0x1f800000
+
+/* System config register offsets */
+#define CFGCON		0x0000
+#define DEVID		0x0020
+#define SYSKEY		0x0030
+#define PMD1		0x0040
+#define PMD7		0x00a0
+#define CFGEBIA		0x00c0
+#define CFGEBIC		0x00d0
+#define CFGPG		0x00e0
+#define CFGMPLL		0x0100
+
+/* Non Volatile Memory (NOR flash) */
+#define PIC32_NVM_BASE		(PIC32_CFG_BASE + 0x0600)
+/* Oscillator Configuration */
+#define PIC32_OSC_BASE		(PIC32_CFG_BASE + 0x1200)
+/* Peripheral Pin Select Input */
+#define PPS_IN_BASE		0x1f801400
+/* Peripheral Pin Select Output */
+#define PPS_OUT_BASE		0x1f801500
+/* Pin Config */
+#define PINCTRL_BASE		0x1f860000
+
+/* USB Core */
+#define PIC32_USB_CORE_BASE	0x1f8e3000
+#define PIC32_USB_CTRL_BASE	0x1f884000
+
+/* SPI1-SPI6 */
+#define PIC32_SPI1_BASE		0x1f821000
+
+/* Prefetch Module */
+#define PREFETCH_BASE		0x1f8e0000
+
+/* DDR2 Controller */
+#define PIC32_DDR2C_BASE	0x1f8e8000
+
+/* DDR2 PHY */
+#define PIC32_DDR2P_BASE	0x1f8e9100
+
+/* EBI */
+#define PIC32_EBI_BASE		0x1f8e1000
+
+/* SQI */
+#define PIC32_SQI_BASE		0x1f8e2000
+
+struct pic32_reg_atomic {
+	u32 raw;
+	u32 clr;
+	u32 set;
+	u32 inv;
+};
+
+#define _CLR_OFFSET	0x04
+#define _SET_OFFSET	0x08
+#define _INV_OFFSET	0x0c
+
+static inline void __iomem *pic32_get_syscfg_base(void)
+{
+	return (void __iomem *)CKSEG1ADDR(PIC32_CFG_BASE);
+}
+
+#endif	/* __PIC32_REGS_H__ */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 03/14] drivers: clk: Add clock driver for Microchip PIC32 Microcontroller.
  2016-01-12 10:18 [U-Boot] [PATCH v3 00/14] Initial Microchip PIC32MZ[DA] Support Purna Chandra Mandal
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 01/14] MIPS: initialize board_init_f() argument to zero Purna Chandra Mandal
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 02/14] MIPS: initial infrastructure for Microchip PIC32 architecture Purna Chandra Mandal
@ 2016-01-12 10:18 ` Purna Chandra Mandal
  2016-01-13 13:38   ` Daniel Schwierzeck
  2016-01-13 14:55   ` Tom Rini
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 04/14] drivers: pinctrl: Add pinctrl driver for Microchip PIC32 Purna Chandra Mandal
                   ` (10 subsequent siblings)
  13 siblings, 2 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-12 10:18 UTC (permalink / raw)
  To: u-boot

PIC32 clock module consists of multiple oscillators, PLLs, mutiplexers
and dividers capable of supplying clock to various controllers
on or off-chip.

Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v3:
- rename clk-pic32.c to clk_pic32.c
- update clock binding documentation
- replace pic32_ioremap() with ioremap()
- separate MPLL initialization constants

Changes in v2:
- add mpll get clock rate

 .../clock/microchip,pic32-clock.txt                |  33 ++
 drivers/clk/Makefile                               |   1 +
 drivers/clk/clk_pic32.c                            | 433 +++++++++++++++++++++
 include/dt-bindings/clock/microchip,clock.h        |  29 ++
 4 files changed, 496 insertions(+)
 create mode 100644 doc/device-tree-bindings/clock/microchip,pic32-clock.txt
 create mode 100644 drivers/clk/clk_pic32.c
 create mode 100644 include/dt-bindings/clock/microchip,clock.h

diff --git a/doc/device-tree-bindings/clock/microchip,pic32-clock.txt b/doc/device-tree-bindings/clock/microchip,pic32-clock.txt
new file mode 100644
index 0000000..02e5ce4
--- /dev/null
+++ b/doc/device-tree-bindings/clock/microchip,pic32-clock.txt
@@ -0,0 +1,33 @@
+* Microchip PIC32 Clock and Oscillator
+
+Microchip PIC32 clock tree consists of few oscillators, PLLs,
+multiplexers and few divider modules capable of supplying clocks
+to various controllers within SoC and also to off-chip.
+
+PIC32 clock controller output is defined by indices as defined
+in [0]
+
+[0] include/dt-bindings/clock/microchip,clock.h
+
+Required Properties:
+- compatible: should be "microchip,pic32mzda_clk"
+- reg: physical base address of the controller and length of memory mapped
+       region.
+- #clock-cells: should be 1.
+
+Example: Clock controller node:
+
+	clock: clk at 1f801200 {
+		compatible = "microchip,pic32mzda_clk";
+		reg = <0x1f801200 0x1000>;
+	};
+
+Example: UART controller node that consumes the clock generated by the clock
+controller:
+
+	uart1: serial at 1f822000 {
+		compatible = "microchip,pic32mzda-uart";
+		reg = <0xbf822000 0x50>;
+		interrupts = <112 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&clock PB2CLK>;
+	};
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 4a6a4a8..adda769 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_CLK) += clk-uclass.o
 obj-$(CONFIG_ROCKCHIP_RK3036) += clk_rk3036.o
 obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o
 obj-$(CONFIG_SANDBOX) += clk_sandbox.o
+obj-$(CONFIG_MACH_PIC32) += clk_pic32.o
diff --git a/drivers/clk/clk_pic32.c b/drivers/clk/clk_pic32.c
new file mode 100644
index 0000000..bb0a1cf
--- /dev/null
+++ b/drivers/clk/clk_pic32.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <div64.h>
+#include <wait_bit.h>
+#include <dm/lists.h>
+#include <asm/io.h>
+#include <mach/pic32.h>
+#include <dt-bindings/clock/microchip,clock.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Primary oscillator */
+#define SYS_POSC_CLK_HZ	24000000
+
+/* FRC clk rate */
+#define SYS_FRC_CLK_HZ	8000000
+
+/* Clock Registers */
+#define OSCCON		0x0000
+#define OSCTUNE		0x0010
+#define SPLLCON		0x0020
+#define REFO1CON	0x0080
+#define REFO1TRIM	0x0090
+#define PB1DIV		0x0140
+
+/* SPLL */
+#define ICLK_MASK	0x00000080
+#define PLLIDIV_MASK	0x00000007
+#define PLLODIV_MASK	0x00000007
+#define CUROSC_MASK	0x00000007
+#define PLLMUL_MASK	0x0000007F
+#define FRCDIV_MASK	0x00000007
+
+/* PBCLK */
+#define PBDIV_MASK	0x00000007
+
+/* SYSCLK MUX */
+#define SCLK_SRC_FRC1	0
+#define SCLK_SRC_SPLL	1
+#define SCLK_SRC_POSC	2
+#define SCLK_SRC_FRC2	7
+
+/* Reference Oscillator Control Reg fields */
+#define REFO_SEL_MASK	0x0f
+#define REFO_SEL_SHIFT	0
+#define REFO_ACTIVE	BIT(8)
+#define REFO_DIVSW_EN	BIT(9)
+#define REFO_OE		BIT(12)
+#define REFO_ON		BIT(15)
+#define REFO_DIV_SHIFT	16
+#define REFO_DIV_MASK	0x7fff
+
+/* Reference Oscillator Trim Register Fields */
+#define REFO_TRIM_REG	0x10
+#define REFO_TRIM_MASK	0x1ff
+#define REFO_TRIM_SHIFT	23
+#define REFO_TRIM_MAX	511
+
+#define ROCLK_SRC_SCLK		0x0
+#define ROCLK_SRC_SPLL		0x7
+#define ROCLK_SRC_ROCLKI	0x8
+
+/* Memory PLL */
+#define MPLL_IDIV		0x3f
+#define MPLL_MULT		0xff
+#define MPLL_ODIV1		0x7
+#define MPLL_ODIV2		0x7
+#define MPLL_VREG_RDY		BIT(23)
+#define MPLL_RDY		BIT(31)
+#define MPLL_IDIV_SHIFT		0
+#define MPLL_MULT_SHIFT		8
+#define MPLL_ODIV1_SHIFT	24
+#define MPLL_ODIV2_SHIFT	27
+#define MPLL_IDIV_INIT		0x03
+#define MPLL_MULT_INIT		0x32
+#define MPLL_ODIV1_INIT		0x02
+#define MPLL_ODIV2_INIT		0x01
+
+struct pic32_clk_priv {
+	void __iomem *iobase;
+	void __iomem *syscfg_base;
+};
+
+static ulong pic32_get_pll_rate(struct pic32_clk_priv *priv)
+{
+	u32 iclk, idiv, odiv, mult;
+	ulong plliclk, v;
+
+	v = readl(priv->iobase + SPLLCON);
+	iclk = (v & ICLK_MASK);
+	idiv = ((v >> 8) & PLLIDIV_MASK) + 1;
+	odiv = ((v >> 24) & PLLODIV_MASK);
+	mult = ((v >> 16) & PLLMUL_MASK) + 1;
+
+	plliclk = iclk ? SYS_FRC_CLK_HZ : SYS_POSC_CLK_HZ;
+
+	if (odiv < 2)
+		odiv = 2;
+	else if (odiv < 5)
+		odiv = (1 << odiv);
+	else
+		odiv = 32;
+
+	return ((plliclk / idiv) * mult) / odiv;
+}
+
+static ulong pic32_get_sysclk(struct pic32_clk_priv *priv)
+{
+	ulong v;
+	ulong hz;
+	ulong div, frcdiv;
+	ulong curr_osc;
+
+	/* get clk source */
+	v = readl(priv->iobase + OSCCON);
+	curr_osc = (v >> 12) & CUROSC_MASK;
+	switch (curr_osc) {
+	case SCLK_SRC_FRC1:
+	case SCLK_SRC_FRC2:
+		frcdiv = ((v >> 24) & FRCDIV_MASK);
+		div = ((1 << frcdiv) + 1) + (128 * (frcdiv == 7));
+		hz = SYS_FRC_CLK_HZ / div;
+		break;
+
+	case SCLK_SRC_SPLL:
+		hz = pic32_get_pll_rate(priv);
+		break;
+
+	case SCLK_SRC_POSC:
+		hz = SYS_POSC_CLK_HZ;
+		break;
+
+	default:
+		hz = 0;
+		printf("clk: unknown sclk_src.\n");
+		break;
+	}
+
+	return hz;
+}
+
+static ulong pic32_get_pbclk(struct pic32_clk_priv *priv, int periph)
+{
+	void __iomem *reg;
+	ulong div, clk_freq;
+
+	WARN_ON((periph < PB1CLK) || (periph > PB7CLK));
+
+	clk_freq = pic32_get_sysclk(priv);
+
+	reg = priv->iobase + PB1DIV + (periph - PB1CLK) * 0x10;
+	div = (readl(reg) & PBDIV_MASK) + 1;
+
+	return clk_freq / div;
+}
+
+static ulong pic32_get_cpuclk(struct pic32_clk_priv *priv)
+{
+	return pic32_get_pbclk(priv, PB7CLK);
+}
+
+static ulong pic32_set_refclk(struct pic32_clk_priv *priv, int periph,
+			      int parent_rate, int rate, int parent_id)
+{
+	void __iomem *reg;
+	u32 div, trim, v;
+	u64 frac;
+
+	WARN_ON((periph < REF1CLK) || (periph > REF5CLK));
+
+	/* calculate dividers,
+	 *   rate = parent_rate / [2 * (div + (trim / 512))]
+	 */
+	if (parent_rate <= rate) {
+		div = 0;
+		trim = 0;
+	} else {
+		div = parent_rate / (rate << 1);
+		frac = parent_rate;
+		frac <<= 8;
+		do_div(frac, rate);
+		frac -= (u64)(div << 9);
+		trim = (frac >= REFO_TRIM_MAX) ? REFO_TRIM_MAX : (u32)frac;
+	}
+
+	reg = priv->iobase + REFO1CON + (periph - REF1CLK) * 0x20;
+
+	/* disable clk */
+	writel(REFO_ON | REFO_OE, reg + _CLR_OFFSET);
+
+	/* wait till previous src change is active */
+	wait_for_bit(__func__, reg, REFO_DIVSW_EN | REFO_ACTIVE,
+		     false, CONFIG_SYS_HZ, false);
+
+	/* parent_id */
+	v = readl(reg);
+	v &= ~(REFO_SEL_MASK << REFO_SEL_SHIFT);
+	v |= (parent_id << REFO_SEL_SHIFT);
+
+	/* apply rodiv */
+	v &= ~(REFO_DIV_MASK << REFO_DIV_SHIFT);
+	v |= (div << REFO_DIV_SHIFT);
+	writel(v, reg);
+
+	/* apply trim */
+	v = readl(reg + REFO_TRIM_REG);
+	v &= ~(REFO_TRIM_MASK << REFO_TRIM_SHIFT);
+	v |= (trim << REFO_TRIM_SHIFT);
+	writel(v, reg + REFO_TRIM_REG);
+
+	/* enable clk */
+	writel(REFO_ON | REFO_OE, reg + _SET_OFFSET);
+
+	/* switch divider */
+	writel(REFO_DIVSW_EN, reg + _SET_OFFSET);
+
+	/* wait for divider switching to complete */
+	return wait_for_bit(__func__, reg, REFO_DIVSW_EN, false,
+			    CONFIG_SYS_HZ, false);
+}
+
+static ulong pic32_get_refclk(struct pic32_clk_priv *priv, int periph)
+{
+	u32 rodiv, rotrim, rosel, v, parent_rate;
+	void __iomem *reg;
+	u64 rate64;
+
+	WARN_ON((periph < REF1CLK) || (periph > REF5CLK));
+
+	reg = priv->iobase + REFO1CON + (periph - REF1CLK) * 0x20;
+	v = readl(reg);
+	/* get rosel */
+	rosel = (v >> REFO_SEL_SHIFT) & REFO_SEL_MASK;
+	/* get div */
+	rodiv = (v >> REFO_DIV_SHIFT) & REFO_DIV_MASK;
+
+	/* get trim */
+	v = readl(reg + REFO_TRIM_REG);
+	rotrim = (v >> REFO_TRIM_SHIFT) & REFO_TRIM_MASK;
+
+	if (!rodiv)
+		return 0;
+
+	/* get parent rate */
+	switch (rosel) {
+	case ROCLK_SRC_SCLK:
+		parent_rate = pic32_get_cpuclk(priv);
+		break;
+	case ROCLK_SRC_SPLL:
+		parent_rate = pic32_get_pll_rate(priv);
+		break;
+	default:
+		parent_rate = 0;
+		break;
+	}
+
+	/* Calculation
+	 * rate = parent_rate / [2 * (div + (trim / 512))]
+	 */
+	if (rotrim) {
+		rodiv <<= 9;
+		rodiv += rotrim;
+		rate64 = parent_rate;
+		rate64 <<= 8;
+		do_div(rate64, rodiv);
+		v = (u32)rate64;
+	} else {
+		v = parent_rate / (rodiv << 1);
+	}
+	return v;
+}
+
+static ulong pic32_get_mpll_rate(struct pic32_clk_priv *priv)
+{
+	u32 v, idiv, mul;
+	u32 odiv1, odiv2;
+	u64 rate;
+
+	v = readl(priv->syscfg_base + CFGMPLL);
+	idiv = v & MPLL_IDIV;
+	mul = (v >> MPLL_MULT_SHIFT) & MPLL_MULT;
+	odiv1 = (v >> MPLL_ODIV1_SHIFT) & MPLL_ODIV1;
+	odiv2 = (v >> MPLL_ODIV2_SHIFT) & MPLL_ODIV2;
+
+	rate = (SYS_POSC_CLK_HZ / idiv) * mul;
+	do_div(rate, odiv1);
+	do_div(rate, odiv2);
+
+	return (ulong)rate;
+}
+
+static int pic32_mpll_init(struct pic32_clk_priv *priv)
+{
+	u32 v, mask;
+
+	/* initialize */
+	v = (MPLL_IDIV_INIT << MPLL_IDIV_SHIFT) |
+	    (MPLL_MULT_INIT << MPLL_MULT_SHIFT) |
+	    (MPLL_ODIV1_INIT << MPLL_ODIV1_SHIFT) |
+	    (MPLL_ODIV2_INIT << MPLL_ODIV2_SHIFT);
+
+	writel(v, priv->syscfg_base + CFGMPLL);
+
+	/* Wait for ready */
+	mask = MPLL_RDY | MPLL_VREG_RDY;
+	return wait_for_bit(__func__, priv->syscfg_base + CFGMPLL, mask,
+			    true, get_tbclk(), false);
+}
+
+static void pic32_clk_init(struct udevice *dev)
+{
+	const void *blob = gd->fdt_blob;
+	struct pic32_clk_priv *priv;
+	ulong rate, pll_hz;
+	char propname[50];
+	int i;
+
+	priv = dev_get_priv(dev);
+	pll_hz = pic32_get_pll_rate(priv);
+
+	/* Initialize REFOs as not initialized and enabled on reset. */
+	for (i = REF1CLK; i <= REF5CLK; i++) {
+		snprintf(propname, sizeof(propname),
+			 "microchip,refo%d-frequency", i - REF1CLK + 1);
+		rate = fdtdec_get_int(blob, dev->of_offset, propname, 0);
+		if (rate)
+			pic32_set_refclk(priv, i, pll_hz, rate, ROCLK_SRC_SPLL);
+	}
+
+	/* Memory PLL */
+	pic32_mpll_init(priv);
+}
+
+static ulong pic32_clk_get_rate(struct udevice *dev)
+{
+	struct pic32_clk_priv *priv = dev_get_priv(dev);
+
+	return pic32_get_cpuclk(priv);
+}
+
+static ulong pic32_get_periph_rate(struct udevice *dev, int periph)
+{
+	struct pic32_clk_priv *priv = dev_get_priv(dev);
+	ulong rate;
+
+	switch (periph) {
+	case PB1CLK ... PB7CLK:
+		rate = pic32_get_pbclk(priv, periph);
+		break;
+	case REF1CLK ... REF5CLK:
+		rate = pic32_get_refclk(priv, periph);
+		break;
+	case PLLCLK:
+		rate = pic32_get_pll_rate(priv);
+		break;
+	case MPLL:
+		rate = pic32_get_mpll_rate(priv);
+		break;
+	default:
+		rate = 0;
+		break;
+	}
+
+	return rate;
+}
+
+static ulong pic32_set_periph_rate(struct udevice *dev, int periph, ulong rate)
+{
+	struct pic32_clk_priv *priv = dev_get_priv(dev);
+	ulong pll_hz;
+
+	switch (periph) {
+	case REF1CLK ... REF5CLK:
+		pll_hz = pic32_get_pll_rate(priv);
+		pic32_set_refclk(priv, periph, pll_hz, rate, ROCLK_SRC_SPLL);
+		break;
+	default:
+		break;
+	}
+
+	return rate;
+}
+
+static struct clk_ops pic32_pic32_clk_ops = {
+	.get_rate = pic32_clk_get_rate,
+	.set_periph_rate = pic32_set_periph_rate,
+	.get_periph_rate = pic32_get_periph_rate,
+};
+
+static int pic32_clk_probe(struct udevice *dev)
+{
+	struct pic32_clk_priv *priv = dev_get_priv(dev);
+	fdt_addr_t addr;
+	fdt_size_t size;
+
+	addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg", &size);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->iobase = ioremap(addr, size);
+	if (!priv->iobase)
+		return -EINVAL;
+
+	priv->syscfg_base = pic32_get_syscfg_base();
+
+	/* initialize clocks */
+	pic32_clk_init(dev);
+
+	return 0;
+}
+
+static const struct udevice_id pic32_clk_ids[] = {
+	{ .compatible = "microchip,pic32mzda_clk"},
+	{}
+};
+
+U_BOOT_DRIVER(pic32_clk) = {
+	.name		= "pic32_clk",
+	.id		= UCLASS_CLK,
+	.of_match	= pic32_clk_ids,
+	.flags		= DM_FLAG_PRE_RELOC,
+	.ops		= &pic32_pic32_clk_ops,
+	.probe		= pic32_clk_probe,
+	.priv_auto_alloc_size = sizeof(struct pic32_clk_priv),
+};
diff --git a/include/dt-bindings/clock/microchip,clock.h b/include/dt-bindings/clock/microchip,clock.h
new file mode 100644
index 0000000..93c222d
--- /dev/null
+++ b/include/dt-bindings/clock/microchip,clock.h
@@ -0,0 +1,29 @@
+/*
+ * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ */
+
+#ifndef __CLK_MICROCHIP_PIC32
+#define __CLK_MICROCHIP_PIC32
+
+/* clock output indices */
+#define BASECLK	0
+#define PLLCLK	1
+#define MPLL	2
+#define SYSCLK	3
+#define PB1CLK	4
+#define PB2CLK	5
+#define PB3CLK	6
+#define PB4CLK	7
+#define PB5CLK	8
+#define PB6CLK	9
+#define PB7CLK	10
+#define REF1CLK	11
+#define REF2CLK	12
+#define REF3CLK	13
+#define REF4CLK	14
+#define REF5CLK	15
+
+#endif	/* __CLK_MICROCHIP_PIC32 */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 04/14] drivers: pinctrl: Add pinctrl driver for Microchip PIC32.
  2016-01-12 10:18 [U-Boot] [PATCH v3 00/14] Initial Microchip PIC32MZ[DA] Support Purna Chandra Mandal
                   ` (2 preceding siblings ...)
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 03/14] drivers: clk: Add clock driver for Microchip PIC32 Microcontroller Purna Chandra Mandal
@ 2016-01-12 10:18 ` Purna Chandra Mandal
  2016-01-13 13:42   ` Daniel Schwierzeck
                     ` (2 more replies)
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 05/14] drivers: gpio: add driver for Microchip PIC32 GPIO controller Purna Chandra Mandal
                   ` (9 subsequent siblings)
  13 siblings, 3 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-12 10:18 UTC (permalink / raw)
  To: u-boot

In PIC32 pin-controller is a combined gpio-controller, pin-mux and
pin-config module. Remappable peripherals are assigned pins through
per-pin based muxing logic. And pin configuration are performed on
specific port registers which are shared along with gpio controller.
Note, non-remappable peripherals have default pins assigned thus require
no muxing.

Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>


---

Changes in v3:
- read register base from device-tree
- add/update comments to explain how pinctrl'r works.
- replace pic32_ioremap() with ioremap().

Changes in v2:
- add pinconf routine for configuring pin property

 drivers/pinctrl/Kconfig         |   9 +
 drivers/pinctrl/Makefile        |   1 +
 drivers/pinctrl/pinctrl_pic32.c | 363 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 373 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl_pic32.c

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 57e6142..292c4e2 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -131,6 +131,15 @@ config PINCTRL_SANDBOX
 	  actually does nothing but print debug messages when pinctrl
 	  operations are invoked.
 
+config PIC32_PINCTRL
+	bool "Microchip PIC32 pin-control and pin-mux driver"
+	depends on DM && MACH_PIC32
+	help
+	  Supports individual pin selection and configuration for each remappable
+	  peripheral available on Microchip PIC32 SoCs. This driver is controlled
+	  by a device tree node which contains both GPIO defintion and pin control
+	  functions.
+
 endif
 
 source "drivers/pinctrl/uniphier/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 70d25dc..b4f4650 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
 obj-$(CONFIG_PINCTRL_SANDBOX)	+= pinctrl-sandbox.o
 
 obj-$(CONFIG_ARCH_UNIPHIER)	+= uniphier/
+obj-$(CONFIG_PIC32_PINCTRL)	+= pinctrl_pic32.o
diff --git a/drivers/pinctrl/pinctrl_pic32.c b/drivers/pinctrl/pinctrl_pic32.c
new file mode 100644
index 0000000..5cf97ec
--- /dev/null
+++ b/drivers/pinctrl/pinctrl_pic32.c
@@ -0,0 +1,363 @@
+/*
+ * Pinctrl driver for Microchip PIC32 SoCs
+ * Copyright (c) 2015 Microchip Technology Inc.
+ * Written by Purna Chandra Mandal <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <dm/pinctrl.h>
+#include <dm/root.h>
+#include <mach/pic32.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* PIC32 has 10 peripheral ports with 16 pins each.
+ * Ports are marked PORTA-PORTK or PORT0-PORT9.
+ */
+enum {
+	PIC32_PORT_A = 0,
+	PIC32_PORT_B = 1,
+	PIC32_PORT_C = 2,
+	PIC32_PORT_D = 3,
+	PIC32_PORT_E = 4,
+	PIC32_PORT_F = 5,
+	PIC32_PORT_G = 6,
+	PIC32_PORT_H = 7,
+	PIC32_PORT_J = 8, /* no PORT_I */
+	PIC32_PORT_K = 9,
+	PIC32_PINS_PER_PORT = 16,
+};
+
+#define PIN_CONFIG_PIC32_DIGITAL	(PIN_CONFIG_END + 1)
+#define PIN_CONFIG_PIC32_ANALOG		(PIN_CONFIG_END + 2)
+
+/* pin configuration descriptor */
+struct pic32_pin_config {
+	u16 port;	/* port number */
+	u16 pin;	/* pin number in the port */
+	u32 config;	/* one of PIN_CONFIG_* */
+};
+#define PIN_CONFIG(_prt, _pin, _cfg) \
+	{.port = (_prt), .pin = (_pin), .config = (_cfg), }
+
+/* In PIC32 muxing is performed at pin-level through two
+ * different set of registers - one set for input functions,
+ * and other for output functions.
+ * Pin configuration is handled through port register.
+ */
+/* Port control registers */
+struct pic32_reg_port {
+	struct pic32_reg_atomic ansel;
+	struct pic32_reg_atomic tris;
+	struct pic32_reg_atomic port;
+	struct pic32_reg_atomic lat;
+	struct pic32_reg_atomic odc;
+	struct pic32_reg_atomic cnpu;
+	struct pic32_reg_atomic cnpd;
+	struct pic32_reg_atomic cncon;
+	struct pic32_reg_atomic unused[8];
+};
+
+/* Input function mux registers */
+struct pic32_reg_in_mux {
+	u32 unused0;
+	u32 int1[4];
+	u32 unused1;
+	u32 t2ck[8];
+	u32 ic1[9];
+	u32 unused2;
+	u32 ocfar;
+	u32 unused3;
+	u32 u1rx;
+	u32 u1cts;
+	u32 u2rx;
+	u32 u2cts;
+	u32 u3rx;
+	u32 u3cts;
+	u32 u4rx;
+	u32 u4cts;
+	u32 u5rx;
+	u32 u5cts;
+	u32 u6rx;
+	u32 u6cts;
+	u32 unused4;
+	u32 sdi1;
+	u32 ss1;
+	u32 unused5;
+	u32 sdi2;
+	u32 ss2;
+	u32 unused6;
+	u32 sdi3;
+	u32 ss3;
+	u32 unused7;
+	u32 sdi4;
+	u32 ss4;
+	u32 unused8;
+	u32 sdi5;
+	u32 ss5;
+	u32 unused9;
+	u32 sdi6;
+	u32 ss6;
+	u32 c1rx;
+	u32 c2rx;
+	u32 refclki1;
+	u32 refclki2;
+	u32 refclki3;
+	u32 refclki4;
+};
+
+/* output mux register offset */
+#define PPS_OUT(__port, __pin) \
+	(((__port) * PIC32_PINS_PER_PORT + (__pin)) << 2)
+
+
+struct pic32_pinctrl_priv {
+	struct pic32_reg_in_mux *mux_in; /* mux input function */
+	struct pic32_reg_port *pinconf; /* pin configuration*/
+	void __iomem *mux_out;	/* mux output function */
+};
+
+enum {
+	PERIPH_ID_UART1,
+	PERIPH_ID_UART2,
+	PERIPH_ID_ETH,
+	PERIPH_ID_USB,
+	PERIPH_ID_SDHCI,
+	PERIPH_ID_I2C1,
+	PERIPH_ID_I2C2,
+	PERIPH_ID_SPI1,
+	PERIPH_ID_SPI2,
+	PERIPH_ID_SQI,
+};
+
+static int pic32_pinconfig_one(struct pic32_pinctrl_priv *priv,
+			       u32 port_nr, u32 pin, u32 param)
+{
+	struct pic32_reg_port *port;
+
+	port = &priv->pinconf[port_nr];
+	switch (param) {
+	case PIN_CONFIG_PIC32_DIGITAL:
+		writel(BIT(pin), &port->ansel.clr);
+		break;
+	case PIN_CONFIG_PIC32_ANALOG:
+		writel(BIT(pin), &port->ansel.set);
+		break;
+	case PIN_CONFIG_INPUT_ENABLE:
+		writel(BIT(pin), &port->tris.set);
+		break;
+	case PIN_CONFIG_OUTPUT:
+		writel(BIT(pin), &port->tris.clr);
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		writel(BIT(pin), &port->cnpu.set);
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		writel(BIT(pin), &port->cnpd.set);
+		break;
+	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+		writel(BIT(pin), &port->odc.set);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int pic32_pinconfig_set(struct pic32_pinctrl_priv *priv,
+			       const struct pic32_pin_config *list, int count)
+{
+	int i;
+
+	for (i = 0 ; i < count; i++)
+		pic32_pinconfig_one(priv, list[i].port,
+				    list[i].pin, list[i].config);
+
+	return 0;
+}
+
+static void pic32_eth_pin_config(struct udevice *dev)
+{
+	struct pic32_pinctrl_priv *priv = dev_get_priv(dev);
+	const struct pic32_pin_config configs[] = {
+		/* EMDC - D11 */
+		PIN_CONFIG(PIC32_PORT_D, 11, PIN_CONFIG_PIC32_DIGITAL),
+		PIN_CONFIG(PIC32_PORT_D, 11, PIN_CONFIG_OUTPUT),
+		/* ETXEN */
+		PIN_CONFIG(PIC32_PORT_D, 6, PIN_CONFIG_PIC32_DIGITAL),
+		PIN_CONFIG(PIC32_PORT_D, 6, PIN_CONFIG_OUTPUT),
+		/* ECRSDV */
+		PIN_CONFIG(PIC32_PORT_H, 13, PIN_CONFIG_PIC32_DIGITAL),
+		PIN_CONFIG(PIC32_PORT_H, 13, PIN_CONFIG_INPUT_ENABLE),
+		/* ERXD0 */
+		PIN_CONFIG(PIC32_PORT_H, 8, PIN_CONFIG_PIC32_DIGITAL),
+		PIN_CONFIG(PIC32_PORT_H, 8, PIN_CONFIG_INPUT_ENABLE),
+		PIN_CONFIG(PIC32_PORT_H, 8, PIN_CONFIG_BIAS_PULL_DOWN),
+		/* ERXD1 */
+		PIN_CONFIG(PIC32_PORT_H, 5, PIN_CONFIG_PIC32_DIGITAL),
+		PIN_CONFIG(PIC32_PORT_H, 5, PIN_CONFIG_INPUT_ENABLE),
+		PIN_CONFIG(PIC32_PORT_H, 5, PIN_CONFIG_BIAS_PULL_DOWN),
+		/* EREFCLK */
+		PIN_CONFIG(PIC32_PORT_J, 11, PIN_CONFIG_PIC32_DIGITAL),
+		PIN_CONFIG(PIC32_PORT_J, 11, PIN_CONFIG_INPUT_ENABLE),
+		/* ETXD1 */
+		PIN_CONFIG(PIC32_PORT_J, 9, PIN_CONFIG_PIC32_DIGITAL),
+		PIN_CONFIG(PIC32_PORT_J, 9, PIN_CONFIG_OUTPUT),
+		/* ETXD0 */
+		PIN_CONFIG(PIC32_PORT_J, 8, PIN_CONFIG_PIC32_DIGITAL),
+		PIN_CONFIG(PIC32_PORT_J, 8, PIN_CONFIG_OUTPUT),
+		/* EMDIO */
+		PIN_CONFIG(PIC32_PORT_J, 1, PIN_CONFIG_PIC32_DIGITAL),
+		PIN_CONFIG(PIC32_PORT_J, 1, PIN_CONFIG_INPUT_ENABLE),
+		/* ERXERR */
+		PIN_CONFIG(PIC32_PORT_F, 3, PIN_CONFIG_PIC32_DIGITAL),
+		PIN_CONFIG(PIC32_PORT_F, 3, PIN_CONFIG_INPUT_ENABLE),
+	};
+
+	pic32_pinconfig_set(priv, configs, ARRAY_SIZE(configs));
+}
+
+static int pic32_pinctrl_request(struct udevice *dev, int func, int flags)
+{
+	struct pic32_pinctrl_priv *priv = dev_get_priv(dev);
+
+	switch (func) {
+	case PERIPH_ID_UART2:
+		/* PPS for U2 RX/TX */
+		writel(0x02, priv->mux_out + PPS_OUT(PIC32_PORT_G, 9));
+		writel(0x05, &priv->mux_in->u2rx); /* B0 */
+		/* set digital mode */
+		pic32_pinconfig_one(priv, PIC32_PORT_G, 9,
+				    PIN_CONFIG_PIC32_DIGITAL);
+		pic32_pinconfig_one(priv, PIC32_PORT_B, 0,
+				    PIN_CONFIG_PIC32_DIGITAL);
+		break;
+	case PERIPH_ID_ETH:
+		pic32_eth_pin_config(dev);
+		break;
+	default:
+		debug("%s: unknown-unhandled case\n", __func__);
+		break;
+	}
+
+	return 0;
+}
+
+static int pic32_pinctrl_get_periph_id(struct udevice *dev,
+				       struct udevice *periph)
+{
+	int ret;
+	u32 cell[2];
+
+	ret = fdtdec_get_int_array(gd->fdt_blob, periph->of_offset,
+				   "interrupts", cell, ARRAY_SIZE(cell));
+	if (ret < 0)
+		return -EINVAL;
+
+	/* interrupt number */
+	switch (cell[0]) {
+	case 112 ... 114:
+		return PERIPH_ID_UART1;
+	case 145 ... 147:
+		return PERIPH_ID_UART2;
+	case 109 ... 111:
+		return PERIPH_ID_SPI1;
+	case 142 ... 144:
+		return PERIPH_ID_SPI2;
+	case 115 ... 117:
+		return PERIPH_ID_I2C1;
+	case 148 ... 150:
+		return PERIPH_ID_I2C2;
+	case 132 ... 133:
+		return PERIPH_ID_USB;
+	case 169:
+		return PERIPH_ID_SQI;
+	case 191:
+		return PERIPH_ID_SDHCI;
+	case 153:
+		return PERIPH_ID_ETH;
+	default:
+		break;
+	}
+
+	return -ENOENT;
+}
+
+static int pic32_pinctrl_set_state_simple(struct udevice *dev,
+					  struct udevice *periph)
+{
+	int func;
+
+	debug("%s: periph %s\n", __func__, periph->name);
+	func = pic32_pinctrl_get_periph_id(dev, periph);
+	if (func < 0)
+		return func;
+	return pic32_pinctrl_request(dev, func, 0);
+}
+
+static struct pinctrl_ops pic32_pinctrl_ops = {
+	.set_state_simple	= pic32_pinctrl_set_state_simple,
+	.request		= pic32_pinctrl_request,
+	.get_periph_id		= pic32_pinctrl_get_periph_id,
+};
+
+static int pic32_pinctrl_probe(struct udevice *dev)
+{
+	struct pic32_pinctrl_priv *priv = dev_get_priv(dev);
+	struct fdt_resource res;
+	void *fdt = (void *)gd->fdt_blob;
+	int node = dev->of_offset;
+	int ret;
+
+	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
+				     "ppsin", &res);
+	if (ret < 0) {
+		printf("pinctrl: resource \"ppsin\" not found\n");
+		return ret;
+	}
+	priv->mux_in = ioremap(res.start, fdt_resource_size(&res));
+
+	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
+				     "ppsout", &res);
+	if (ret < 0) {
+		printf("pinctrl: resource \"ppsout\" not found\n");
+		return ret;
+	}
+	priv->mux_out = ioremap(res.start, fdt_resource_size(&res));
+
+	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
+				     "port", &res);
+	if (ret < 0) {
+		printf("pinctrl: resource \"port\" not found\n");
+		return ret;
+	}
+	priv->pinconf = ioremap(res.start, fdt_resource_size(&res));
+
+	return 0;
+}
+
+static int pic32_pinctrl_bind(struct udevice *dev)
+{
+	/* scan child GPIO banks */
+	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+}
+
+static const struct udevice_id pic32_pinctrl_ids[] = {
+	{ .compatible = "microchip,pic32mzda-pinctrl" },
+	{ }
+};
+
+U_BOOT_DRIVER(pinctrl_pic32) = {
+	.name		= "pinctrl_pic32",
+	.id		= UCLASS_PINCTRL,
+	.of_match	= pic32_pinctrl_ids,
+	.ops		= &pic32_pinctrl_ops,
+	.probe		= pic32_pinctrl_probe,
+	.bind		= pic32_pinctrl_bind,
+	.priv_auto_alloc_size = sizeof(struct pic32_pinctrl_priv),
+};
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 05/14] drivers: gpio: add driver for Microchip PIC32 GPIO controller.
  2016-01-12 10:18 [U-Boot] [PATCH v3 00/14] Initial Microchip PIC32MZ[DA] Support Purna Chandra Mandal
                   ` (3 preceding siblings ...)
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 04/14] drivers: pinctrl: Add pinctrl driver for Microchip PIC32 Purna Chandra Mandal
@ 2016-01-12 10:18 ` Purna Chandra Mandal
  2016-01-13 13:46   ` Daniel Schwierzeck
                     ` (2 more replies)
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 06/14] drivers: serial: add driver for Microchip PIC32 UART controller Purna Chandra Mandal
                   ` (8 subsequent siblings)
  13 siblings, 3 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-12 10:18 UTC (permalink / raw)
  To: u-boot

In PIC32 GPIO controller is part of PIC32 pin controller.
PIC32 has ten independently programmable ports and each with multiple pins.
Each of these pins can be configured and used as GPIO, provided they
are not in use for other peripherals.

Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>

---

Changes in v3:
- add check on dev_get_addr()

Changes in v2: None

 drivers/gpio/Kconfig      |   7 ++
 drivers/gpio/Makefile     |   2 +-
 drivers/gpio/pic32_gpio.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 183 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpio/pic32_gpio.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index e60e9fd..13e9a6a 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -83,4 +83,11 @@ config VYBRID_GPIO
 	help
 	  Say yes here to support Vybrid vf610 GPIOs.
 
+config PIC32_GPIO
+	bool "Microchip PIC32 GPIO driver"
+	depends on DM_GPIO
+	default y if MACH_PIC32
+	help
+	  Say yes here to support Microchip PIC32 GPIOs.
+
 endmenu
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index fb4fd25..845a6d4 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -46,4 +46,4 @@ obj-$(CONFIG_STM32_GPIO)	+= stm32_gpio.o
 obj-$(CONFIG_ZYNQ_GPIO)		+= zynq_gpio.o
 obj-$(CONFIG_VYBRID_GPIO)	+= vybrid_gpio.o
 obj-$(CONFIG_HIKEY_GPIO)	+= hi6220_gpio.o
-
+obj-$(CONFIG_PIC32_GPIO)	+= pic32_gpio.o
diff --git a/drivers/gpio/pic32_gpio.c b/drivers/gpio/pic32_gpio.c
new file mode 100644
index 0000000..5b23af4
--- /dev/null
+++ b/drivers/gpio/pic32_gpio.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2015 Microchip Technology Inc
+ * Purna Chandra Mandal <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <linux/compat.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <mach/pic32.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Peripheral Pin Control */
+struct pic32_reg_port {
+	struct pic32_reg_atomic ansel;
+	struct pic32_reg_atomic tris;
+	struct pic32_reg_atomic port;
+	struct pic32_reg_atomic lat;
+	struct pic32_reg_atomic open_drain;
+	struct pic32_reg_atomic cnpu;
+	struct pic32_reg_atomic cnpd;
+	struct pic32_reg_atomic cncon;
+};
+
+enum {
+	MICROCHIP_GPIO_DIR_OUT,
+	MICROCHIP_GPIO_DIR_IN,
+	MICROCHIP_GPIOS_PER_BANK = 16,
+};
+
+struct pic32_gpio_priv {
+	struct pic32_reg_port *regs;
+	char name[2];
+};
+
+static int pic32_gpio_get_value(struct udevice *dev, unsigned offset)
+{
+	struct pic32_gpio_priv *priv = dev_get_priv(dev);
+
+	return !!(readl(&priv->regs->port.raw) & BIT(offset));
+}
+
+static int pic32_gpio_set_value(struct udevice *dev, unsigned offset,
+				int value)
+{
+	struct pic32_gpio_priv *priv = dev_get_priv(dev);
+	int mask = BIT(offset);
+
+	if (value)
+		writel(mask, &priv->regs->port.set);
+	else
+		writel(mask, &priv->regs->port.clr);
+
+	return 0;
+}
+
+static int pic32_gpio_direction(struct udevice *dev, unsigned offset)
+{
+	struct pic32_gpio_priv *priv = dev_get_priv(dev);
+
+	if (readl(&priv->regs->ansel.raw) & BIT(offset))
+		return -1;
+
+	if (readl(&priv->regs->tris.raw) & BIT(offset))
+		return MICROCHIP_GPIO_DIR_IN;
+	else
+		return MICROCHIP_GPIO_DIR_OUT;
+}
+
+static int pic32_gpio_direction_input(struct udevice *dev, unsigned offset)
+{
+	struct pic32_gpio_priv *priv = dev_get_priv(dev);
+	int mask = BIT(offset);
+
+	writel(mask, &priv->regs->ansel.clr);
+	writel(mask, &priv->regs->tris.set);
+
+	return 0;
+}
+
+static int pic32_gpio_direction_output(struct udevice *dev,
+				       unsigned offset, int value)
+{
+	struct pic32_gpio_priv *priv = dev_get_priv(dev);
+	int mask = BIT(offset);
+
+	writel(mask, &priv->regs->ansel.clr);
+	writel(mask, &priv->regs->tris.clr);
+
+	pic32_gpio_set_value(dev, offset, value);
+	return 0;
+}
+
+static int pic32_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
+			    struct fdtdec_phandle_args *args)
+{
+	desc->offset = args->args[0];
+	desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
+
+	return 0;
+}
+
+static int pic32_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+	int ret = GPIOF_UNUSED;
+
+	switch (pic32_gpio_direction(dev, offset)) {
+	case MICROCHIP_GPIO_DIR_OUT:
+		ret = GPIOF_OUTPUT;
+		break;
+	case MICROCHIP_GPIO_DIR_IN:
+		ret = GPIOF_INPUT;
+		break;
+	default:
+		ret = GPIOF_UNUSED;
+		break;
+	}
+	return ret;
+}
+
+static const struct dm_gpio_ops gpio_pic32_ops = {
+	.direction_input	= pic32_gpio_direction_input,
+	.direction_output	= pic32_gpio_direction_output,
+	.get_value		= pic32_gpio_get_value,
+	.set_value		= pic32_gpio_set_value,
+	.get_function		= pic32_gpio_get_function,
+	.xlate			= pic32_gpio_xlate,
+};
+
+static int pic32_gpio_probe(struct udevice *dev)
+{
+	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct pic32_gpio_priv *priv = dev_get_priv(dev);
+	fdt_addr_t addr;
+	fdt_size_t size;
+	char *end;
+	int bank;
+
+	addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg", &size);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->regs = ioremap(addr, size);
+	if (!priv->regs)
+		return -EINVAL;
+
+	uc_priv->gpio_count = MICROCHIP_GPIOS_PER_BANK;
+	end = strrchr(dev->name, '@');
+	bank = trailing_strtoln(dev->name, end);
+	priv->name[0] = 'A' + bank;
+	uc_priv->bank_name = priv->name;
+
+	return 0;
+}
+
+static const struct udevice_id pic32_gpio_ids[] = {
+	{ .compatible = "microchip,pic32mzda-gpio" },
+	{ }
+};
+
+U_BOOT_DRIVER(gpio_pic32) = {
+	.name		= "gpio_pic32",
+	.id		= UCLASS_GPIO,
+	.of_match	= pic32_gpio_ids,
+	.ops		= &gpio_pic32_ops,
+	.probe		= pic32_gpio_probe,
+	.priv_auto_alloc_size	= sizeof(struct pic32_gpio_priv),
+};
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 06/14] drivers: serial: add driver for Microchip PIC32 UART controller.
  2016-01-12 10:18 [U-Boot] [PATCH v3 00/14] Initial Microchip PIC32MZ[DA] Support Purna Chandra Mandal
                   ` (4 preceding siblings ...)
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 05/14] drivers: gpio: add driver for Microchip PIC32 GPIO controller Purna Chandra Mandal
@ 2016-01-12 10:18 ` Purna Chandra Mandal
  2016-01-13 13:49   ` Daniel Schwierzeck
                     ` (2 more replies)
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 07/14] drivers: ddr: Add DDR2 SDRAM controller driver for Microchip PIC32 Purna Chandra Mandal
                   ` (7 subsequent siblings)
  13 siblings, 3 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-12 10:18 UTC (permalink / raw)
  To: u-boot

From: Paul Thacker <paul.thacker@microchip.com>

This adds PIC32 UART controller support based on driver model.

Signed-off-by: Paul Thacker <paul.thacker@microchip.com>
Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>


---

Changes in v3:
- remove ofdata_to_platdata, and replace platdata with priv
- remove special handling of '\r' as being handled by serial-uclass
- remove loop to wait for space in tx buffer before pumping char

Changes in v2:
- fix missing/corrupted chars during baud rate change
- remove loop until any char is avaialbale in getc()

 .../serial/microchip,pic32-uart.txt                |   5 +
 drivers/serial/Kconfig                             |  13 ++
 drivers/serial/Makefile                            |   1 +
 drivers/serial/serial_pic32.c                      | 199 +++++++++++++++++++++
 4 files changed, 218 insertions(+)
 create mode 100644 doc/device-tree-bindings/serial/microchip,pic32-uart.txt
 create mode 100644 drivers/serial/serial_pic32.c

diff --git a/doc/device-tree-bindings/serial/microchip,pic32-uart.txt b/doc/device-tree-bindings/serial/microchip,pic32-uart.txt
new file mode 100644
index 0000000..f00e215
--- /dev/null
+++ b/doc/device-tree-bindings/serial/microchip,pic32-uart.txt
@@ -0,0 +1,5 @@
+* Microchip PIC32 serial UART
+
+Required properties:
+- compatible: must be "microchip,pic32mzda-uart".
+- reg: exactly one register range.
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 1fc287e..9763ea1 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -107,6 +107,14 @@ config DEBUG_UART_APBUART
 	  will need to provide parameters to make this work. The driver will
 	  be available until the real driver model serial is running.
 
+config DEBUG_UART_PIC32
+	bool "Microchip PIC32"
+	help
+	  Select this to enable a debug UART using the serial_pic32 driver. You
+	  will need to provide parameters to make this work. The driver will
+	  be available until the real driver model serial is running.
+
+
 endchoice
 
 config DEBUG_UART_BASE
@@ -223,4 +231,9 @@ config UNIPHIER_SERIAL
 	  If you have a UniPhier based board and want to use the on-chip
 	  serial ports, say Y to this option. If unsure, say N.
 
+config PIC32_SERIAL
+	bool "Support for Microchip PIC32 on-chip UART"
+	help
+	  Support for the UART found on Microchip PIC32 SoC's.
+
 endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index dd87147..57cd38b 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_MXS_AUART) += mxs_auart.o
 obj-$(CONFIG_ARC_SERIAL) += serial_arc.o
 obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o
 obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o
+obj-$(CONFIG_PIC32_SERIAL) += serial_pic32.o
 
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_USB_TTY) += usbtty.o
diff --git a/drivers/serial/serial_pic32.c b/drivers/serial/serial_pic32.c
new file mode 100644
index 0000000..ee9d056
--- /dev/null
+++ b/drivers/serial/serial_pic32.c
@@ -0,0 +1,199 @@
+/*
+ * (c) 2015 Paul Thacker <paul.thacker@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ */
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <serial.h>
+#include <wait_bit.h>
+#include <mach/pic32.h>
+#include <dt-bindings/clock/microchip,clock.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* UART Control Registers */
+#define U_MOD		0x00
+#define U_MODCLR	(U_MOD + _CLR_OFFSET)
+#define U_MODSET	(U_MOD + _SET_OFFSET)
+#define U_STA		0x10
+#define U_STACLR	(U_STA + _CLR_OFFSET)
+#define U_STASET	(U_STA + _SET_OFFSET)
+#define U_TXR		0x20
+#define U_RXR		0x30
+#define U_BRG		0x40
+
+/* U_MOD bits */
+#define UART_ENABLE		BIT(15)
+
+/* U_STA bits */
+#define UART_RX_ENABLE		BIT(12)
+#define UART_TX_BRK		BIT(11)
+#define UART_TX_ENABLE		BIT(10)
+#define UART_TX_FULL		BIT(9)
+#define UART_TX_EMPTY		BIT(8)
+#define UART_RX_OERR		BIT(1)
+#define UART_RX_DATA_AVAIL	BIT(0)
+
+struct pic32_uart_priv {
+	void __iomem *base;
+	ulong uartclk;
+};
+
+/*
+ * Initialize the serial port with the given baudrate.
+ * The settings are always 8 data bits, no parity, 1 stop bit, no start bits.
+ */
+static int pic32_serial_init(void __iomem *base, ulong clk, u32 baudrate)
+{
+	u32 div = DIV_ROUND_CLOSEST(clk, baudrate * 16);
+
+	/* wait for TX FIFO to empty */
+	wait_for_bit(__func__, base + U_STA, UART_TX_EMPTY,
+		     true, CONFIG_SYS_HZ, false);
+
+	/* send break */
+	writel(UART_TX_BRK, base + U_STASET);
+
+	/* disable and clear mode */
+	writel(0, base + U_MOD);
+	writel(0, base + U_STA);
+
+	/* set baud rate generator */
+	writel(div - 1, base + U_BRG);
+
+	/* enable the UART for TX and RX */
+	writel(UART_TX_ENABLE | UART_RX_ENABLE, base + U_STASET);
+
+	/* enable the UART */
+	writel(UART_ENABLE, base + U_MODSET);
+	return 0;
+}
+
+/* Check number of characters ready in RX Fifo */
+static int pic32_uart_pending_input(void __iomem *base)
+{
+	/* check if rx buffer overrun error has occurred */
+	if (readl(base + U_STA) & UART_RX_OERR) {
+		readl(base + U_RXR);
+
+		/* clear OERR to keep receiving */
+		writel(UART_RX_OERR, base + U_STACLR);
+	}
+
+	return readl(base + U_STA) & UART_RX_DATA_AVAIL;
+}
+
+static int pic32_uart_pending(struct udevice *dev, bool input)
+{
+	struct pic32_uart_priv *priv = dev_get_priv(dev);
+
+	if (input)
+		return pic32_uart_pending_input(priv->base);
+
+	return !(readl(priv->base + U_STA) & UART_TX_EMPTY);
+}
+
+static int pic32_uart_setbrg(struct udevice *dev, int baudrate)
+{
+	struct pic32_uart_priv *priv = dev_get_priv(dev);
+
+	return pic32_serial_init(priv->base, priv->uartclk, baudrate);
+}
+
+static int pic32_uart_putc(struct udevice *dev, const char ch)
+{
+	struct pic32_uart_priv *priv = dev_get_priv(dev);
+
+	/* Check if Tx FIFO is full */
+	if (readl(priv->base + U_STA) & UART_TX_FULL)
+		return -EAGAIN;
+
+	/* pump the char to tx buffer */
+	writel(ch, priv->base + U_TXR);
+
+	return 0;
+}
+
+static int pic32_uart_getc(struct udevice *dev)
+{
+	struct pic32_uart_priv *priv = dev_get_priv(dev);
+
+	/* return error if RX fifo is empty */
+	if (!pic32_uart_pending_input(priv->base))
+		return -EAGAIN;
+
+	/* read the character from rx buffer */
+	return readl(priv->base + U_RXR) & 0xff;
+}
+
+static int pic32_uart_probe(struct udevice *dev)
+{
+	struct pic32_uart_priv *priv = dev_get_priv(dev);
+	struct udevice *clkdev;
+	fdt_addr_t addr;
+	fdt_size_t size;
+	int ret;
+
+	/* get address */
+	addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg", &size);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->base = ioremap(addr, size);
+	if (!priv->base)
+		return -EINVAL;
+
+	/* get clock rate */
+	ret = uclass_get_device(UCLASS_CLK, 0, &clkdev);
+	if (ret) {
+		printf("clk class not found, %d\n", ret);
+		return ret;
+	}
+	priv->uartclk = clk_get_periph_rate(clkdev, PB2CLK);
+
+	/* initialize serial */
+	return pic32_serial_init(priv->base, priv->uartclk, CONFIG_BAUDRATE);
+}
+
+static const struct dm_serial_ops pic32_uart_ops = {
+	.putc		= pic32_uart_putc,
+	.pending	= pic32_uart_pending,
+	.getc		= pic32_uart_getc,
+	.setbrg		= pic32_uart_setbrg,
+};
+
+static const struct udevice_id pic32_uart_ids[] = {
+	{ .compatible = "microchip,pic32mzda-uart" },
+	{}
+};
+
+U_BOOT_DRIVER(pic32_serial) = {
+	.name		= "pic32-uart",
+	.id		= UCLASS_SERIAL,
+	.of_match	= pic32_uart_ids,
+	.probe		= pic32_uart_probe,
+	.ops		= &pic32_uart_ops,
+	.flags		= DM_FLAG_PRE_RELOC,
+	.priv_auto_alloc_size = sizeof(struct pic32_uart_priv),
+};
+
+#ifdef CONFIG_DEBUG_UART_PIC32
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+	void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE;
+
+	pic32_serial_init(base, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+	writel(ch, CONFIG_DEBUG_UART_BASE + U_TXR);
+}
+
+DEBUG_UART_FUNCS
+#endif
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 07/14] drivers: ddr: Add DDR2 SDRAM controller driver for Microchip PIC32.
  2016-01-12 10:18 [U-Boot] [PATCH v3 00/14] Initial Microchip PIC32MZ[DA] Support Purna Chandra Mandal
                   ` (5 preceding siblings ...)
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 06/14] drivers: serial: add driver for Microchip PIC32 UART controller Purna Chandra Mandal
@ 2016-01-12 10:18 ` Purna Chandra Mandal
  2016-01-13 13:53   ` Daniel Schwierzeck
                     ` (2 more replies)
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 08/14] MIPS: Add support for Microchip PIC32MZ[DA] SoC family Purna Chandra Mandal
                   ` (6 subsequent siblings)
  13 siblings, 3 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-12 10:18 UTC (permalink / raw)
  To: u-boot

This driver initializes PIC32 DDR2 SDRAM controller and internal DDR2 Phy module.
DDR2 controller operates in half-rate mode (upto 533MHZ frequency).

Signed-off-by: Paul Thacker <paul.thacker@microchip.com>
Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>


---

Changes in v3:
- annotating fixed table with const
- fix camel-case in ddr2 timing parameters
- fix cmd index parameter of host_load_cmd().
- fix compilation warning

Changes in v2:
- move ddr2 initialization from board/microchip/ to drivers/ddr/microchip

 arch/mips/mach-pic32/include/mach/ddr.h |  32 ++++
 drivers/Makefile                        |   1 +
 drivers/ddr/microchip/Makefile          |   6 +
 drivers/ddr/microchip/ddr2.c            | 278 ++++++++++++++++++++++++++++++++
 drivers/ddr/microchip/ddr2_regs.h       | 148 +++++++++++++++++
 drivers/ddr/microchip/ddr2_timing.h     |  65 ++++++++
 6 files changed, 530 insertions(+)
 create mode 100644 arch/mips/mach-pic32/include/mach/ddr.h
 create mode 100644 drivers/ddr/microchip/Makefile
 create mode 100644 drivers/ddr/microchip/ddr2.c
 create mode 100644 drivers/ddr/microchip/ddr2_regs.h
 create mode 100644 drivers/ddr/microchip/ddr2_timing.h

diff --git a/arch/mips/mach-pic32/include/mach/ddr.h b/arch/mips/mach-pic32/include/mach/ddr.h
new file mode 100644
index 0000000..00abfa3
--- /dev/null
+++ b/arch/mips/mach-pic32/include/mach/ddr.h
@@ -0,0 +1,32 @@
+/*
+ * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ */
+
+#ifndef __MICROCHIP_PIC32_DDR_H
+#define __MICROCHIP_PIC32_DDR_H
+
+/* called by initdram() function */
+void ddr2_phy_init(void);
+void ddr2_ctrl_init(void);
+phys_size_t ddr2_calculate_size(void);
+
+/* Maximum number of agents */
+#define NUM_AGENTS		5
+
+/* Board can provide agent specific parameters for arbitration by
+ * filling struct ddr2_arbiter_params for all the agents and
+ * implementing board_get_ddr_arbiter_params() to return the filled
+ * structure.
+ */
+struct ddr2_arbiter_params {
+	u32 min_limit;	/* min bursts to execute per arbitration */
+	u32 req_period; /* request period threshold for accepted cmds */
+	u32 min_cmd_acpt; /* min number of accepted cmds */
+};
+
+const struct ddr2_arbiter_params *board_get_ddr_arbiter_params(void);
+
+#endif /* __MICROCHIP_PIC32_DDR_H */
diff --git a/drivers/Makefile b/drivers/Makefile
index c9031f2..0ab54d9 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -68,4 +68,5 @@ obj-y += soc/
 obj-$(CONFIG_REMOTEPROC) += remoteproc/
 obj-y += thermal/
 
+obj-$(CONFIG_MACH_PIC32) += ddr/microchip/
 endif
diff --git a/drivers/ddr/microchip/Makefile b/drivers/ddr/microchip/Makefile
new file mode 100644
index 0000000..305c48b
--- /dev/null
+++ b/drivers/ddr/microchip/Makefile
@@ -0,0 +1,6 @@
+#
+# Copyright (C) 2015 Microchip Technology Inc.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+obj-$(CONFIG_MACH_PIC32) += ddr2.o
diff --git a/drivers/ddr/microchip/ddr2.c b/drivers/ddr/microchip/ddr2.c
new file mode 100644
index 0000000..6056418
--- /dev/null
+++ b/drivers/ddr/microchip/ddr2.c
@@ -0,0 +1,278 @@
+/*
+ * (c) 2015 Paul Thacker <paul.thacker@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ */
+#include <common.h>
+#include <wait_bit.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <mach/pic32.h>
+#include <mach/ddr.h>
+
+#include "ddr2_regs.h"
+#include "ddr2_timing.h"
+
+/* init DDR2 Phy */
+void ddr2_phy_init(void)
+{
+	struct ddr2_phy_regs *ddr2_phy;
+	u32 pad_ctl;
+
+	ddr2_phy = ioremap(PIC32_DDR2P_BASE, sizeof(*ddr2_phy));
+
+	/* PHY_DLL_RECALIB */
+	writel(DELAY_START_VAL(3) | DISABLE_RECALIB(0) |
+	       RECALIB_CNT(0x10), &ddr2_phy->dll_recalib);
+
+	/* PHY_PAD_CTRL */
+	pad_ctl = ODT_SEL | ODT_EN | DRIVE_SEL(0) |
+		  ODT_PULLDOWN(2) | ODT_PULLUP(3) |
+		  EXTRA_OEN_CLK(0) | NOEXT_DLL |
+		  DLR_DFT_WRCMD | HALF_RATE |
+		  DRVSTR_PFET(0xe) | DRVSTR_NFET(0xe) |
+		  RCVR_EN | PREAMBLE_DLY(2);
+	writel(pad_ctl, &ddr2_phy->pad_ctrl);
+
+	/* SCL_CONFIG_0 */
+	writel(SCL_BURST8 | SCL_DDR_CONNECTED | SCL_RCAS_LAT(RL) |
+	       SCL_ODTCSWW, &ddr2_phy->scl_config_1);
+
+	/* SCL_CONFIG_1 */
+	writel(SCL_CSEN | SCL_WCAS_LAT(WL), &ddr2_phy->scl_config_2);
+
+	/* SCL_LAT */
+	writel(SCL_CAPCLKDLY(3) | SCL_DDRCLKDLY(4), &ddr2_phy->scl_latency);
+}
+
+/* start phy self calibration logic */
+static int ddr2_phy_calib_start(void)
+{
+	struct ddr2_phy_regs *ddr2_phy;
+
+	ddr2_phy = ioremap(PIC32_DDR2P_BASE, sizeof(*ddr2_phy));
+
+	/* DDR Phy SCL Start */
+	writel(SCL_START | SCL_EN, &ddr2_phy->scl_start);
+
+	/* Wait for SCL for data byte to pass */
+	return wait_for_bit(__func__, &ddr2_phy->scl_start, SCL_LUBPASS,
+			    true, CONFIG_SYS_HZ, false);
+}
+
+/* DDR2 Controller initialization */
+
+/* Target Agent Arbiter */
+static void ddr_set_arbiter(struct ddr2_ctrl_regs *ctrl,
+			    const struct ddr2_arbiter_params *const param)
+{
+	int i;
+
+	for (i = 0; i < NUM_AGENTS; i++) {
+		/* set min burst size */
+		writel(i * MIN_LIM_WIDTH, &ctrl->tsel);
+		writel(param->min_limit, &ctrl->minlim);
+
+		/* set request period (4 * req_period clocks) */
+		writel(i * RQST_PERIOD_WIDTH, &ctrl->tsel);
+		writel(param->req_period, &ctrl->reqprd);
+
+		/* set number of burst accepted */
+		writel(i * MIN_CMDACPT_WIDTH, &ctrl->tsel);
+		writel(param->min_cmd_acpt, &ctrl->mincmd);
+	}
+}
+
+const struct ddr2_arbiter_params *__weak board_get_ddr_arbiter_params(void)
+{
+	/* default arbiter parameters */
+	static const struct ddr2_arbiter_params arb_params[] = {
+		{ .min_limit = 0x1f, .req_period = 0xff, .min_cmd_acpt = 0x04,},
+		{ .min_limit = 0x1f, .req_period = 0xff, .min_cmd_acpt = 0x10,},
+		{ .min_limit = 0x1f, .req_period = 0xff, .min_cmd_acpt = 0x10,},
+		{ .min_limit = 0x04, .req_period = 0xff, .min_cmd_acpt = 0x04,},
+		{ .min_limit = 0x04, .req_period = 0xff, .min_cmd_acpt = 0x04,},
+	};
+
+	return &arb_params[0];
+}
+
+static void host_load_cmd(struct ddr2_ctrl_regs *ctrl, u32 cmd_idx,
+			  u32 hostcmd2, u32 hostcmd1, u32 delay)
+{
+	u32 hc_delay;
+
+	hc_delay = max_t(u32, DIV_ROUND_UP(delay, T_CK), 2) - 2;
+	writel(hostcmd1, &ctrl->cmd10[cmd_idx]);
+	writel((hostcmd2 & 0x7ff) | (hc_delay << 11), &ctrl->cmd20[cmd_idx]);
+}
+
+/* init DDR2 Controller */
+void ddr2_ctrl_init(void)
+{
+	u32 wr2prech, rd2prech, wr2rd, wr2rd_cs;
+	u32 ras2ras, ras2cas, prech2ras, temp;
+	const struct ddr2_arbiter_params *arb_params;
+	struct ddr2_ctrl_regs *ctrl;
+
+	ctrl = ioremap(PIC32_DDR2C_BASE, sizeof(*ctrl));
+
+	/* PIC32 DDR2 controller always work in HALF_RATE */
+	writel(HALF_RATE_MODE, &ctrl->memwidth);
+
+	/* Set arbiter configuration per target */
+	arb_params = board_get_ddr_arbiter_params();
+	ddr_set_arbiter(ctrl, arb_params);
+
+	/* Address Configuration, model {CS, ROW, BA, COL} */
+	writel((ROW_ADDR_RSHIFT | (BA_RSHFT << 8) | (CS_ADDR_RSHIFT << 16) |
+	       (COL_HI_RSHFT << 24) | (SB_PRI << 29)  |
+	       (EN_AUTO_PRECH << 30)), &ctrl->memcfg0);
+
+	writel(ROW_ADDR_MASK, &ctrl->memcfg1);
+	writel(COL_HI_MASK, &ctrl->memcfg2);
+	writel(COL_LO_MASK, &ctrl->memcfg3);
+	writel(BA_MASK | (CS_ADDR_MASK << 8), &ctrl->memcfg4);
+
+	/* Refresh Config */
+	writel(REFCNT_CLK(DIV_ROUND_UP(T_RFI, T_CK_CTRL) - 2) |
+	       REFDLY_CLK(DIV_ROUND_UP(T_RFC_MIN, T_CK_CTRL) - 2) |
+	       MAX_PEND_REF(7),
+	       &ctrl->refcfg);
+
+	/* Power Config */
+	writel(ECC_EN(0) | ERR_CORR_EN(0) | EN_AUTO_PWR_DN(0) |
+	       EN_AUTO_SELF_REF(3) | PWR_DN_DLY(8) |
+	       SELF_REF_DLY(17) | PRECH_PWR_DN_ONLY(0),
+	       &ctrl->pwrcfg);
+
+	/* Delay Config */
+	wr2rd = max_t(u32, DIV_ROUND_UP(T_WTR, T_CK_CTRL),
+		      DIV_ROUND_UP(T_WTR_TCK, 2)) + WL + BL;
+	wr2rd_cs = max_t(u32, wr2rd - 1, 3);
+	wr2prech = DIV_ROUND_UP(T_WR, T_CK_CTRL) + WL + BL;
+	rd2prech = max_t(u32, DIV_ROUND_UP(T_RTP, T_CK_CTRL),
+			 DIV_ROUND_UP(T_RTP_TCK, 2)) + BL - 2;
+	ras2ras = max_t(u32, DIV_ROUND_UP(T_RRD, T_CK_CTRL),
+			DIV_ROUND_UP(T_RRD_TCK, 2)) - 1;
+	ras2cas = DIV_ROUND_UP(T_RCD, T_CK_CTRL) - 1;
+	prech2ras = DIV_ROUND_UP(T_RP, T_CK_CTRL) - 1;
+
+	writel(((wr2rd & 0x0f) |
+	       ((wr2rd_cs & 0x0f) << 4) |
+	       ((BL - 1) << 8) |
+	       (BL << 12) |
+	       ((BL - 1) << 16) |
+	       ((BL - 1) << 20) |
+	       ((BL + 2) << 24) |
+	       ((RL - WL + 3) << 28)), &ctrl->dlycfg0);
+
+	writel(((T_CKE_TCK - 1) |
+	       (((DIV_ROUND_UP(T_DLLK, 2) - 2) & 0xff) << 8) |
+	       ((T_CKE_TCK - 1) << 16) |
+	       ((max_t(u32, T_XP_TCK, T_CKE_TCK) - 1) << 20) |
+	       ((wr2prech >> 4) << 26) |
+	       ((wr2rd >> 4) << 27) |
+	       ((wr2rd_cs >> 4) << 28) |
+	       (((RL + 5) >> 4) << 29) |
+	       ((DIV_ROUND_UP(T_DLLK, 2) >> 8) << 30)), &ctrl->dlycfg1);
+
+	writel((DIV_ROUND_UP(T_RP, T_CK_CTRL) |
+	       (rd2prech << 8) |
+	       ((wr2prech & 0x0f) << 12) |
+	       (ras2ras << 16) |
+	       (ras2cas << 20) |
+	       (prech2ras << 24) |
+	       ((RL + 3) << 28)), &ctrl->dlycfg2);
+
+	writel(((DIV_ROUND_UP(T_RAS_MIN, T_CK_CTRL) - 1) |
+	       ((DIV_ROUND_UP(T_RC, T_CK_CTRL) - 1) << 8) |
+	       ((DIV_ROUND_UP(T_FAW, T_CK_CTRL) - 1) << 16)),
+	       &ctrl->dlycfg3);
+
+	/* ODT Config */
+	writel(0x0, &ctrl->odtcfg);
+	writel(BIT(16), &ctrl->odtencfg);
+	writel(ODTRDLY(RL - 3) | ODTWDLY(WL - 3) | ODTRLEN(2) | ODTWLEN(3),
+	       &ctrl->odtcfg);
+
+	/* Transfer Configuration */
+	writel(NXTDATRQDLY(2) | NXDATAVDLY(4) | RDATENDLY(2) |
+	       MAX_BURST(3) | (7 << 28) | BIG_ENDIAN(0),
+	       &ctrl->xfercfg);
+
+	/* DRAM Initialization */
+	/* CKE high after reset and wait 400 nsec */
+	host_load_cmd(ctrl, 0, 0, IDLE_NOP, 400000);
+
+	/* issue precharge all command */
+	host_load_cmd(ctrl, 1, 0x04, PRECH_ALL_CMD, T_RP + T_CK);
+
+	/* initialize EMR2 */
+	host_load_cmd(ctrl, 2, 0x200, LOAD_MODE_CMD, T_MRD_TCK * T_CK);
+
+	/* initialize EMR3 */
+	host_load_cmd(ctrl, 3, 0x300, LOAD_MODE_CMD, T_MRD_TCK * T_CK);
+
+	/*
+	 * RDQS disable, DQSB enable, OCD exit, 150 ohm termination,
+	 * AL=0, DLL enable
+	 */
+	host_load_cmd(ctrl, 4, 0x100,
+		      LOAD_MODE_CMD | (0x40 << 24), T_MRD_TCK * T_CK);
+	/*
+	 * PD fast exit, WR REC = T_WR in clocks -1,
+	 * DLL reset, CAS = RL, burst = 4
+	 */
+	temp = ((DIV_ROUND_UP(T_WR, T_CK) - 1) << 1) | 1;
+	host_load_cmd(ctrl, 5, temp, LOAD_MODE_CMD | (RL << 28) | (2 << 24),
+		      T_MRD_TCK * T_CK);
+
+	/* issue precharge all command */
+	host_load_cmd(ctrl, 6, 4, PRECH_ALL_CMD, T_RP + T_CK);
+
+	/* issue refresh command */
+	host_load_cmd(ctrl, 7, 0, REF_CMD, T_RFC_MIN);
+
+	/* issue refresh command */
+	host_load_cmd(ctrl, 8, 0, REF_CMD, T_RFC_MIN);
+
+	/* Mode register programming as before without DLL reset */
+	host_load_cmd(ctrl, 9, temp, LOAD_MODE_CMD | (RL << 28) | (3 << 24),
+		      T_MRD_TCK * T_CK);
+
+	/* extended mode register same as before with OCD default */
+	host_load_cmd(ctrl, 10, 0x103, LOAD_MODE_CMD | (0xc << 24),
+		      T_MRD_TCK * T_CK);
+
+	/* extended mode register same as before with OCD exit */
+	host_load_cmd(ctrl, 11, 0x100, LOAD_MODE_CMD | (0x4 << 28),
+		      140 * T_CK);
+
+	writel(CMD_VALID | NUMHOSTCMD(11), &ctrl->cmdissue);
+
+	/* start memory initialization */
+	writel(INIT_START, &ctrl->memcon);
+
+	/* wait for all host cmds to be transmitted */
+	wait_for_bit(__func__, &ctrl->cmdissue, CMD_VALID, false,
+		     CONFIG_SYS_HZ, false);
+
+	/* inform all cmds issued, ready for normal operation */
+	writel(INIT_START | INIT_DONE, &ctrl->memcon);
+
+	/* perform phy caliberation */
+	if (ddr2_phy_calib_start())
+		printf("ddr2: phy calib failed\n");
+}
+
+phys_size_t ddr2_calculate_size(void)
+{
+	u32 temp;
+
+	temp = 1 << (COL_BITS + BA_BITS + ROW_BITS);
+	/* 16-bit data width between controller and DIMM */
+	temp = temp * CS_BITS * (16 / 8);
+	return (phys_size_t)temp;
+}
diff --git a/drivers/ddr/microchip/ddr2_regs.h b/drivers/ddr/microchip/ddr2_regs.h
new file mode 100644
index 0000000..0f4b159
--- /dev/null
+++ b/drivers/ddr/microchip/ddr2_regs.h
@@ -0,0 +1,148 @@
+/*
+ * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ */
+
+#ifndef __MICROCHIP_DDR2_REGS_H
+#define __MICROCHIP_DDR2_REGS_H
+
+#include <linux/bitops.h>
+
+/* DDR2 Controller */
+struct ddr2_ctrl_regs {
+	u32 tsel;
+	u32 minlim;
+	u32 reqprd;
+	u32 mincmd;
+	u32 memcon;
+	u32 memcfg0;
+	u32 memcfg1;
+	u32 memcfg2;
+	u32 memcfg3;
+	u32 memcfg4;
+	u32 refcfg;
+	u32 pwrcfg;
+	u32 dlycfg0;
+	u32 dlycfg1;
+	u32 dlycfg2;
+	u32 dlycfg3;
+	u32 odtcfg;
+	u32 xfercfg;
+	u32 cmdissue;
+	u32 odtencfg;
+	u32 memwidth;
+	u32 unused[11];
+	u32 cmd10[16];
+	u32 cmd20[16];
+};
+
+/* Arbiter Config */
+#define MIN_LIM_WIDTH		5
+#define RQST_PERIOD_WIDTH	8
+#define MIN_CMDACPT_WIDTH	8
+
+/* Refresh Config */
+#define REFCNT_CLK(x)		(x)
+#define REFDLY_CLK(x)		((x) << 16)
+#define MAX_PEND_REF(x)		((x) << 24)
+
+/* Power Config */
+#define PRECH_PWR_DN_ONLY(x)	((x) << 22)
+#define SELF_REF_DLY(x)		((x) << 12)
+#define PWR_DN_DLY(x)		((x) << 4)
+#define EN_AUTO_SELF_REF(x)	((x) << 3)
+#define EN_AUTO_PWR_DN(x)	((x) << 2)
+#define ERR_CORR_EN(x)		((x) << 1)
+#define ECC_EN(x)		(x)
+
+/* Memory Width */
+#define HALF_RATE_MODE		BIT(3)
+
+/* Delay Config */
+#define ODTWLEN(x)	((x) << 20)
+#define ODTRLEN(x)	((x) << 16)
+#define ODTWDLY(x)	((x) << 12)
+#define ODTRDLY(x)	((x) << 8)
+
+/* Xfer Config */
+#define BIG_ENDIAN(x)	((x) << 31)
+#define MAX_BURST(x)	((x) << 24)
+#define RDATENDLY(x)	((x) << 16)
+#define NXDATAVDLY(x)	((x) << 4)
+#define NXTDATRQDLY(x)	((x) << 0)
+
+/* Host Commands */
+#define IDLE_NOP	0x00ffffff
+#define PRECH_ALL_CMD	0x00fff401
+#define REF_CMD		0x00fff801
+#define LOAD_MODE_CMD	0x00fff001
+#define CKE_LOW		0x00ffeffe
+
+#define NUM_HOST_CMDS	12
+
+/* Host CMD Issue */
+#define CMD_VALID	BIT(4)
+#define NUMHOSTCMD(x)	(x)
+
+/* Memory Control */
+#define INIT_DONE	BIT(1)
+#define INIT_START	BIT(0)
+
+/* Address Control */
+#define EN_AUTO_PRECH		0
+#define SB_PRI			1
+
+/* DDR2 Phy Register */
+struct ddr2_phy_regs {
+	u32 scl_start;
+	u32 unused1[2];
+	u32 scl_latency;
+	u32 unused2[2];
+	u32 scl_config_1;
+	u32 scl_config_2;
+	u32 pad_ctrl;
+	u32 dll_recalib;
+};
+
+/* PHY PAD CONTROL */
+#define ODT_SEL			BIT(0)
+#define ODT_EN			BIT(1)
+#define DRIVE_SEL(x)		((x) << 2)
+#define ODT_PULLDOWN(x)		((x) << 4)
+#define ODT_PULLUP(x)		((x) << 6)
+#define EXTRA_OEN_CLK(x)	((x) << 8)
+#define NOEXT_DLL		BIT(9)
+#define DLR_DFT_WRCMD		BIT(13)
+#define HALF_RATE		BIT(14)
+#define DRVSTR_PFET(x)		((x) << 16)
+#define DRVSTR_NFET(x)		((x) << 20)
+#define RCVR_EN			BIT(28)
+#define PREAMBLE_DLY(x)		((x) << 29)
+
+/* PHY DLL RECALIBRATE */
+#define RECALIB_CNT(x)		((x) << 8)
+#define DISABLE_RECALIB(x)	((x) << 26)
+#define DELAY_START_VAL(x)	((x) << 28)
+
+/* PHY SCL CONFIG1 */
+#define SCL_BURST8		BIT(0)
+#define SCL_DDR_CONNECTED		BIT(1)
+#define SCL_RCAS_LAT(x)		((x) << 4)
+#define SCL_ODTCSWW		BIT(24)
+
+/* PHY SCL CONFIG2 */
+#define SCL_CSEN		BIT(0)
+#define SCL_WCAS_LAT(x)		((x) << 8)
+
+/* PHY SCL Latency */
+#define SCL_CAPCLKDLY(x)	((x) << 0)
+#define SCL_DDRCLKDLY(x)	((x) << 4)
+
+/* PHY SCL START */
+#define SCL_START		BIT(28)
+#define SCL_EN			BIT(26)
+#define SCL_LUBPASS		(BIT(1) | BIT(0))
+
+#endif	/* __MICROCHIP_DDR2_REGS_H */
diff --git a/drivers/ddr/microchip/ddr2_timing.h b/drivers/ddr/microchip/ddr2_timing.h
new file mode 100644
index 0000000..5895f9d
--- /dev/null
+++ b/drivers/ddr/microchip/ddr2_timing.h
@@ -0,0 +1,65 @@
+/*
+ * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ */
+
+#ifndef __MICROCHIP_DDR2_TIMING_H
+#define __MICROCHIP_DDR2_TIMING_H
+
+/* MPLL freq is 400MHz */
+#define T_CK		2500    /* 2500 psec */
+#define T_CK_CTRL	(T_CK * 2)
+
+/* Burst length in cycles */
+#define BL		2
+/* default CAS latency for all speed grades */
+#define RL		5
+/* default write latency for all speed grades = CL-1 */
+#define WL		4
+
+/* From Micron MT47H64M16HR-3 data sheet */
+#define T_RFC_MIN	127500	/* psec */
+#define T_WR		15000	/* psec */
+#define T_RP		12500	/* psec */
+#define T_RCD		12500	/* psec */
+#define T_RRD		7500	/* psec */
+/* T_RRD_TCK is minimum of 2 clk periods, regardless of freq */
+#define T_RRD_TCK	2
+#define T_WTR		7500	/* psec */
+/* T_WTR_TCK is minimum of 2 clk periods, regardless of freq */
+#define T_WTR_TCK	2
+#define T_RTP		7500	/* psec */
+#define T_RTP_TCK	(BL / 2)
+#define T_XP_TCK	2	/* clocks */
+#define T_CKE_TCK	3	/* clocks */
+#define T_XSNR		(T_RFC_MIN + 10000) /* psec */
+#define T_DLLK		200     /* clocks */
+#define T_RAS_MIN	45000   /* psec */
+#define T_RC		57500   /* psec */
+#define T_FAW		35000   /* psec */
+#define T_MRD_TCK	2       /* clocks */
+#define T_RFI		7800000 /* psec */
+
+/* DDR Addressing */
+#define COL_BITS	10
+#define BA_BITS		3
+#define ROW_BITS	13
+#define CS_BITS		1
+
+/* DDR Addressing scheme: {CS, ROW, BA, COL} */
+#define COL_HI_RSHFT	0
+#define COL_HI_MASK	0
+#define COL_LO_MASK	((1 << COL_BITS) - 1)
+
+#define BA_RSHFT	COL_BITS
+#define BA_MASK		((1 << BA_BITS) - 1)
+
+#define ROW_ADDR_RSHIFT	(BA_RSHFT + BA_BITS)
+#define ROW_ADDR_MASK	((1 << ROW_BITS) - 1)
+
+#define CS_ADDR_RSHIFT	0
+#define CS_ADDR_MASK	0
+
+#endif	/* __MICROCHIP_DDR2_TIMING_H */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 08/14] MIPS: Add support for Microchip PIC32MZ[DA] SoC family.
  2016-01-12 10:18 [U-Boot] [PATCH v3 00/14] Initial Microchip PIC32MZ[DA] Support Purna Chandra Mandal
                   ` (6 preceding siblings ...)
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 07/14] drivers: ddr: Add DDR2 SDRAM controller driver for Microchip PIC32 Purna Chandra Mandal
@ 2016-01-12 10:18 ` Purna Chandra Mandal
  2016-01-13 14:49   ` Daniel Schwierzeck
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 09/14] board: Add Microchip PIC32MZ[DA]-Starter-Kit board Purna Chandra Mandal
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-12 10:18 UTC (permalink / raw)
  To: u-boot

Add Microchip PIC32MZ[DA] SoC family support.

Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>

---

Changes in v3:
- drop forcing CONFIG_MIPS_BOOT_* selection in mach-pic32/Kconfig
- indent assembly instructions in delay slot
- made GPIO-nodes child of pinctrl-node in devicetree
- replace pic32_ioremap() with ioremap()

Changes in v2:
- drop board_early_init_f
- use macro LEAF(), END() for lowlevel_init assembly
- move initialization of board_init_f() argument to common start.S
- move initdram() from board/microchip/ to mach-pic32/cpu.c
- remove MIPS virtual address in favor physical one in dts file

 arch/mips/dts/pic32mzda.dtsi              | 153 ++++++++++++++++++++++++++++++
 arch/mips/mach-pic32/Kconfig              |  20 +++-
 arch/mips/mach-pic32/Makefile             |   2 +-
 arch/mips/mach-pic32/cpu.c                | 147 ++++++++++++++++++++++++++++
 arch/mips/mach-pic32/include/mach/pic32.h |   3 +
 arch/mips/mach-pic32/lowlevel_init.S      |  27 ++++++
 arch/mips/mach-pic32/reset.c              |  36 +++++++
 7 files changed, 386 insertions(+), 2 deletions(-)
 create mode 100644 arch/mips/dts/pic32mzda.dtsi
 create mode 100644 arch/mips/mach-pic32/lowlevel_init.S
 create mode 100644 arch/mips/mach-pic32/reset.c

diff --git a/arch/mips/dts/pic32mzda.dtsi b/arch/mips/dts/pic32mzda.dtsi
new file mode 100644
index 0000000..fe8b13a
--- /dev/null
+++ b/arch/mips/dts/pic32mzda.dtsi
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2015 Microchip Technology, Inc.
+ * Purna Chandra Mandal, <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/clock/microchip,clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "skeleton.dtsi"
+
+/ {
+	compatible = "microchip,pic32mzda", "microchip,pic32mz";
+
+	aliases {
+		gpio0 = &gpioA;
+		gpio1 = &gpioB;
+		gpio2 = &gpioC;
+		gpio3 = &gpioD;
+		gpio4 = &gpioE;
+		gpio5 = &gpioF;
+		gpio6 = &gpioG;
+		gpio7 = &gpioH;
+		gpio8 = &gpioJ;
+		gpio9 = &gpioK;
+	};
+
+	cpus {
+		cpu at 0 {
+			compatible = "mips,mips14kc";
+		};
+	};
+
+	clock: clk at 1f801200 {
+		compatible = "microchip,pic32mzda_clk";
+		reg = <0x1f801200 0x1000>;
+		clock-cells = <1>;
+	};
+
+	uart1: serial at 1f822000 {
+		compatible = "microchip,pic32mzda-uart";
+		reg = <0x1f822000 0x50>;
+		interrupts = <112 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+		clocks = <&clock PB2CLK>;
+	};
+
+	uart2: serial at 1f822200 {
+		compatible = "microchip,pic32mzda-uart";
+		reg = <0x1f822200 0x50>;
+		interrupts = <145 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&clock PB2CLK>;
+		status = "disabled";
+	};
+
+	uart6: serial at 1f822a00 {
+		compatible = "microchip,pic32mzda-uart";
+		reg = <0x1f822a00 0x50>;
+		interrupts = <188 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&clock PB2CLK>;
+		status = "disabled";
+	};
+
+	evic: interrupt-controller at 1f810000 {
+		compatible = "microchip,pic32mzda-evic";
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		reg = <0x1f810000 0x1000>;
+	};
+
+	pinctrl: pinctrl at 1f801400 {
+		compatible = "microchip,pic32mzda-pinctrl";
+		reg = <0x1f801400 0x100>, /* in  */
+		      <0x1f801500 0x200>, /* out */
+		      <0x1f860000 0xa00>; /* port */
+		reg-names = "ppsin","ppsout","port";
+		status = "disabled";
+
+		ranges = <0 0x1f860000 0xa00>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		gpioA: gpio0 at 0 {
+			compatible = "microchip,pic32mzda-gpio";
+			reg = <0x000 0x48>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpioB: gpio1 at 100 {
+			compatible = "microchip,pic32mzda-gpio";
+			reg = <0x100 0x48>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpioC: gpio2 at 200 {
+			compatible = "microchip,pic32mzda-gpio";
+			reg = <0x200 0x48>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpioD: gpio3 at 300 {
+			compatible = "microchip,pic32mzda-gpio";
+			reg = <0x300 0x48>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpioE: gpio4 at 400 {
+			compatible = "microchip,pic32mzda-gpio";
+			reg = <0x400 0x48>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpioF: gpio5 at 500 {
+			compatible = "microchip,pic32mzda-gpio";
+			reg = <0x500 0x48>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpioG: gpio6 at 600 {
+			compatible = "microchip,pic32mzda-gpio";
+			reg = <0x600 0x48>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpioH: gpio7 at 700 {
+			compatible = "microchip,pic32mzda-gpio";
+			reg = <0x700 0x48>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpioJ: gpio8 at 800 {
+			compatible = "microchip,pic32mzda-gpio";
+			reg = <0x800 0x48>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpioK: gpio9 at 900 {
+			compatible = "microchip,pic32mzda-gpio";
+			reg = <0x900 0x48>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+	};
+};
diff --git a/arch/mips/mach-pic32/Kconfig b/arch/mips/mach-pic32/Kconfig
index c1cc5e3..74be9fb 100644
--- a/arch/mips/mach-pic32/Kconfig
+++ b/arch/mips/mach-pic32/Kconfig
@@ -2,6 +2,24 @@ menu "Microchip PIC32 platforms"
 	depends on MACH_PIC32
 
 config SYS_SOC
-	default "none"
+	default "pic32mzda" if SOC_PIC32MZDA
+
+choice
+	prompt "PIC32 SoC select"
+
+config SOC_PIC32MZDA
+	bool "Microchip PIC32MZ[DA] family"
+	select SUPPORTS_LITTLE_ENDIAN
+	select SUPPORTS_CPU_MIPS32_R1
+	select SUPPORTS_CPU_MIPS32_R2
+	select MIPS_L1_CACHE_SHIFT_4
+	select SYS_MIPS_CACHE_INIT_RAM_LOAD
+	select DM_SERIAL
+	select PIC32_SERIAL
+	select PIC32_PINCTRL
+	help
+	  This supports Microchip PIC32MZ[DA] family of microcontrollers.
+
+endchoice
 
 endmenu
diff --git a/arch/mips/mach-pic32/Makefile b/arch/mips/mach-pic32/Makefile
index cb42607..e321e65 100644
--- a/arch/mips/mach-pic32/Makefile
+++ b/arch/mips/mach-pic32/Makefile
@@ -4,4 +4,4 @@
 # SPDX-License-Identifier:      GPL-2.0+
 #
 
-obj-y = cpu.o
+obj-y = cpu.o lowlevel_init.o reset.o
\ No newline at end of file
diff --git a/arch/mips/mach-pic32/cpu.c b/arch/mips/mach-pic32/cpu.c
index 58fd3ab..8ecdef8 100644
--- a/arch/mips/mach-pic32/cpu.c
+++ b/arch/mips/mach-pic32/cpu.c
@@ -6,8 +6,155 @@
  *
  */
 #include <common.h>
+#include <dm.h>
+#include <clk.h>
+#include <debug_uart.h>
+#include <linux/compiler.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <mach/pic32.h>
+#include <mach/ddr.h>
+#include <dt-bindings/clock/microchip,clock.h>
 
+/* Flash prefetch */
+#define PRECON          0x00
+
+/* Flash ECCCON */
+#define ECC_MASK	0x03
+#define ECC_SHIFT	4
+
+#define CLK_MHZ(x)	((x) / 1000000)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static ulong clk_get_cpu_rate(void)
+{
+	int ret;
+	struct udevice *dev;
+
+	ret = uclass_get_device(UCLASS_CLK, 0, &dev);
+	if (ret) {
+		panic("uclass-clk: device not found\n");
+		return 0;
+	}
+
+	return clk_get_rate(dev);
+}
+
+/* initialize prefetch module related to cpu_clk */
+static void prefetch_init(void)
+{
+	struct pic32_reg_atomic *regs;
+	const void __iomem *base;
+	int v, nr_waits;
+	ulong rate;
+
+	/* cpu frequency in MHZ */
+	rate = clk_get_cpu_rate() / 1000000;
+
+	/* get flash ECC type */
+	base = pic32_get_syscfg_base();
+	v = (readl(base + CFGCON) >> ECC_SHIFT) & ECC_MASK;
+
+	if (v < 2) {
+		if (rate < 66)
+			nr_waits = 0;
+		else if (rate < 133)
+			nr_waits = 1;
+		else
+			nr_waits = 2;
+	} else {
+		if (rate <= 83)
+			nr_waits = 0;
+		else if (rate <= 166)
+			nr_waits = 1;
+		else
+			nr_waits = 2;
+	}
+
+	regs = ioremap(PREFETCH_BASE + PRECON, sizeof(*regs));
+	writel(nr_waits, &regs->raw);
+
+	/* Enable prefetch for all */
+	writel(0x30, &regs->set);
+	iounmap(regs);
+}
+
+/* arch specific CPU init after DM */
+int arch_cpu_init_dm(void)
+{
+	/* flash prefetch */
+	prefetch_init();
+	return 0;
+}
+
+/* Un-gate DDR2 modules (gated by default) */
+static void ddr2_pmd_ungate(void)
+{
+	void __iomem *regs;
+
+	regs = pic32_get_syscfg_base();
+	writel(0, regs + PMD7);
+}
+
+/* initialize the DDR2 Controller and DDR2 PHY */
 phys_size_t initdram(int board_type)
 {
+	ddr2_pmd_ungate();
+	ddr2_phy_init();
+	ddr2_ctrl_init();
+	return ddr2_calculate_size();
+}
+
+int misc_init_r(void)
+{
+	set_io_port_base(0);
+	return 0;
+}
+
+#ifdef CONFIG_DISPLAY_BOARDINFO
+const char *get_core_name(void)
+{
+	u32 proc_id;
+	const char *str;
+
+	proc_id = read_c0_prid();
+	switch (proc_id) {
+	case 0x19e28:
+		str = "PIC32MZ[DA]";
+		break;
+	default:
+		str = "UNKNOWN";
+	}
+
+	return str;
+}
+#endif
+#ifdef CONFIG_CMD_CLK
+int soc_clk_dump(void)
+{
+	int i, ret;
+	struct udevice *dev;
+
+	ret = uclass_get_device(UCLASS_CLK, 0, &dev);
+	if (ret) {
+		printf("clk-uclass not found\n");
+		return ret;
+	}
+
+	printf("PLL Speed: %lu MHz\n",
+	       CLK_MHZ(clk_get_periph_rate(dev, PLLCLK)));
+	printf("CPU Speed: %lu MHz\n", CLK_MHZ(clk_get_rate(dev)));
+	printf("MPLL Speed: %lu MHz\n",
+	       CLK_MHZ(clk_get_periph_rate(dev, MPLL)));
+
+	for (i = PB1CLK; i <= PB7CLK; i++)
+		printf("PB%d Clock Speed: %lu MHz\n", i - PB1CLK + 1,
+		       CLK_MHZ(clk_get_periph_rate(dev, i)));
+
+	for (i = REF1CLK; i <= REF5CLK; i++)
+		printf("REFO%d Clock Speed: %lu MHz\n", i - REF1CLK + 1,
+		       CLK_MHZ(clk_get_periph_rate(dev, i)));
 	return 0;
 }
+#endif
diff --git a/arch/mips/mach-pic32/include/mach/pic32.h b/arch/mips/mach-pic32/include/mach/pic32.h
index 7e41810..16bfacf 100644
--- a/arch/mips/mach-pic32/include/mach/pic32.h
+++ b/arch/mips/mach-pic32/include/mach/pic32.h
@@ -73,4 +73,7 @@ static inline void __iomem *pic32_get_syscfg_base(void)
 	return (void __iomem *)CKSEG1ADDR(PIC32_CFG_BASE);
 }
 
+/* Core */
+const char *get_core_name(void);
+
 #endif	/* __PIC32_REGS_H__ */
diff --git a/arch/mips/mach-pic32/lowlevel_init.S b/arch/mips/mach-pic32/lowlevel_init.S
new file mode 100644
index 0000000..e37bebb
--- /dev/null
+++ b/arch/mips/mach-pic32/lowlevel_init.S
@@ -0,0 +1,27 @@
+/*
+ * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+*/
+
+#include <config.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/asm.h>
+
+LEAF(lowlevel_init)
+	/*
+	 * Establish Cause
+	 * (set IV bit)
+	 */
+	li	t1, 0x00800000
+	mtc0	t1, CP0_CAUSE
+
+	/* Establish Wired (and Random) */
+	mtc0	zero, CP0_WIRED
+	 nop
+
+	jr	ra
+	 nop
+	END(lowlevel_init)
diff --git a/arch/mips/mach-pic32/reset.c b/arch/mips/mach-pic32/reset.c
new file mode 100644
index 0000000..66c6833
--- /dev/null
+++ b/arch/mips/mach-pic32/reset.c
@@ -0,0 +1,36 @@
+/*
+ * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <mach/pic32.h>
+
+/* SYSKEY */
+#define UNLOCK_KEY1	0xaa996655
+#define UNLOCK_KEY2	0x556699aa
+#define LOCK_KEY	0
+
+#define RSWRST          0x1250
+
+void _machine_restart(void)
+{
+	void __iomem *base;
+
+	base = pic32_get_syscfg_base();
+
+	/* unlock sequence */
+	writel(LOCK_KEY, base + SYSKEY);
+	writel(UNLOCK_KEY1, base + SYSKEY);
+	writel(UNLOCK_KEY2, base + SYSKEY);
+
+	/* soft reset */
+	writel(0x1, base + RSWRST);
+	(void) readl(base + RSWRST);
+
+	while (1)
+		;
+}
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 09/14] board: Add Microchip PIC32MZ[DA]-Starter-Kit board.
  2016-01-12 10:18 [U-Boot] [PATCH v3 00/14] Initial Microchip PIC32MZ[DA] Support Purna Chandra Mandal
                   ` (7 preceding siblings ...)
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 08/14] MIPS: Add support for Microchip PIC32MZ[DA] SoC family Purna Chandra Mandal
@ 2016-01-12 10:18 ` Purna Chandra Mandal
  2016-01-13 14:56   ` Tom Rini
  2016-01-13 15:03   ` Daniel Schwierzeck
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 10/14] drivers: mmc: add driver for Microchip PIC32 SDHCI controller Purna Chandra Mandal
                   ` (4 subsequent siblings)
  13 siblings, 2 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-12 10:18 UTC (permalink / raw)
  To: u-boot

This adds support for Microchip PIC32MZ[DA] StarterKit board
based on a PIC32MZ[DA] family of microcontroller.

Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>


---

Changes in v3:
- drop SKIP_LOWLEVEL_INIT, GBL_DATA_OFFSET from config header
- move CMD_MEMTEST, CMD_MEMINFO to defconfig
- increase SYS_MALLOC_F_LEN to 0x600
- use auto-generated defconfig - no hand edit

Changes in v2:
- move CONFIG_SYS_TEXT_BASE (from board/*/config.mk) to include/configs/<board>.h

 arch/mips/dts/Makefile                |   2 +-
 arch/mips/dts/pic32mzda_sk.dts        |  38 ++++
 arch/mips/mach-pic32/Kconfig          |  13 ++
 board/microchip/pic32mzda/Kconfig     |  13 ++
 board/microchip/pic32mzda/MAINTAINERS |   6 +
 board/microchip/pic32mzda/Makefile    |   7 +
 board/microchip/pic32mzda/README      |  22 ++
 board/microchip/pic32mzda/pic32mzda.c |  31 +++
 configs/pic32mzdask_defconfig         | 416 ++++++++++++++++++++++++++++++++++
 include/configs/pic32mzdask.h         |  94 ++++++++
 10 files changed, 641 insertions(+), 1 deletion(-)
 create mode 100644 arch/mips/dts/pic32mzda_sk.dts
 create mode 100644 board/microchip/pic32mzda/Kconfig
 create mode 100644 board/microchip/pic32mzda/MAINTAINERS
 create mode 100644 board/microchip/pic32mzda/Makefile
 create mode 100644 board/microchip/pic32mzda/README
 create mode 100644 board/microchip/pic32mzda/pic32mzda.c
 create mode 100644 configs/pic32mzdask_defconfig
 create mode 100644 include/configs/pic32mzdask.h

diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile
index 47b6eb5..b513918 100644
--- a/arch/mips/dts/Makefile
+++ b/arch/mips/dts/Makefile
@@ -2,7 +2,7 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-dtb-y +=
+dtb-$(CONFIG_TARGET_PIC32MZDASK) += pic32mzda_sk.dtb
 
 targets += $(dtb-y)
 
diff --git a/arch/mips/dts/pic32mzda_sk.dts b/arch/mips/dts/pic32mzda_sk.dts
new file mode 100644
index 0000000..99e7f64
--- /dev/null
+++ b/arch/mips/dts/pic32mzda_sk.dts
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 Purna Chandra Mandal, purna.mandal at microchip.com
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+
+#include "pic32mzda.dtsi"
+
+/ {
+	model = "Microchip PIC32MZDASK";
+	compatible = "microchip,pic32mzdask", "microchip,pic32mzda";
+
+	aliases {
+		console = &uart2;
+		serial0 = &uart2;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&clock {
+	status = "okay";
+	u-boot,dm-pre-reloc;
+};
+
+&pinctrl {
+	status = "okay";
+	u-boot,dm-pre-reloc;
+};
+
+&uart2 {
+	status = "okay";
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/mips/mach-pic32/Kconfig b/arch/mips/mach-pic32/Kconfig
index 74be9fb..d665f63 100644
--- a/arch/mips/mach-pic32/Kconfig
+++ b/arch/mips/mach-pic32/Kconfig
@@ -22,4 +22,17 @@ config SOC_PIC32MZDA
 
 endchoice
 
+choice
+	prompt "Board select"
+
+config TARGET_PIC32MZDASK
+	bool "Microchip PIC32MZ[DA] Starter Kit"
+	depends on SOC_PIC32MZDA
+	help
+	  This supports Microchip PIC32MZ[DA] Starter Kit.
+
+endchoice
+
+source "board/microchip/pic32mzda/Kconfig"
+
 endmenu
diff --git a/board/microchip/pic32mzda/Kconfig b/board/microchip/pic32mzda/Kconfig
new file mode 100644
index 0000000..8acb393
--- /dev/null
+++ b/board/microchip/pic32mzda/Kconfig
@@ -0,0 +1,13 @@
+
+if TARGET_PIC32MZDASK
+
+config SYS_BOARD
+	default "pic32mzda"
+
+config SYS_VENDOR
+	default "microchip"
+
+config SYS_CONFIG_NAME
+	default "pic32mzdask"
+
+endif
diff --git a/board/microchip/pic32mzda/MAINTAINERS b/board/microchip/pic32mzda/MAINTAINERS
new file mode 100644
index 0000000..c934f1a
--- /dev/null
+++ b/board/microchip/pic32mzda/MAINTAINERS
@@ -0,0 +1,6 @@
+PIC32MZDASK BOARD
+M:	Purna Chandra Mandal <purna.mandal@microchip.com>
+S:	Maintained
+F:	board/microchip/pic32mzda/
+F:	include/configs/pic32mzdask.h
+F:	configs/pic32mzdask_defconfig
diff --git a/board/microchip/pic32mzda/Makefile b/board/microchip/pic32mzda/Makefile
new file mode 100644
index 0000000..3629530
--- /dev/null
+++ b/board/microchip/pic32mzda/Makefile
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2015
+# Purna Chandra Mandal, purna.mandal at microchip.com.
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+obj-y := pic32mzda.o
diff --git a/board/microchip/pic32mzda/README b/board/microchip/pic32mzda/README
new file mode 100644
index 0000000..91d16ab
--- /dev/null
+++ b/board/microchip/pic32mzda/README
@@ -0,0 +1,22 @@
+/*
+ * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
+ */
+
+PIC32MZ[DA] Starter Kit
+----------------------------------------
+PIC32MZ[DA] Starter Kit is based on PIC32MZ[DA] family of micro-controller.
+This family is powered by MIPS M14KEC 32bit general purpose core and has
+advanced microcontroller features and peripherals.
+
+This processor boots with proprietary stage1 bootloader running from internal
+boot-flash. Stage1 bootloader inturns locates and jumps to U-Boot programmed
+on internal program-flash. Finally U-Boot loads OS image (along with other
+required files for booting) from either uSD card, or ethernet, or from USB
+storage.
+
+To boot Linux following three files are mandatory - uEnv.txt (custom U-Boot
+environment file), uImage, *.dtb (platform device-tree-blob file).
+
+U-Boot jumps to Linux using UHI specification.
+
+Visit http://microchip.com for details.
diff --git a/board/microchip/pic32mzda/pic32mzda.c b/board/microchip/pic32mzda/pic32mzda.c
new file mode 100644
index 0000000..afe2ab8
--- /dev/null
+++ b/board/microchip/pic32mzda/pic32mzda.c
@@ -0,0 +1,31 @@
+/*
+ * Microchip PIC32MZ[DA] Starter Kit board
+ *
+ * Copyright (C) 2015, Microchip Technology Inc.
+ * Purna Chandra Mandal <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <clk.h>
+#include <mach/pic32.h>
+
+#ifdef CONFIG_DISPLAY_BOARDINFO
+int checkboard(void)
+{
+	ulong rate = 0;
+	struct udevice *dev;
+
+	printf("Core: %s\n", get_core_name());
+
+	if (!uclass_get_device(UCLASS_CLK, 0, &dev)) {
+		rate = clk_get_rate(dev);
+		printf("CPU Speed: %lu MHz\n", rate / 1000000);
+	}
+
+	return 0;
+}
+#endif
diff --git a/configs/pic32mzdask_defconfig b/configs/pic32mzdask_defconfig
new file mode 100644
index 0000000..3483eb0
--- /dev/null
+++ b/configs/pic32mzdask_defconfig
@@ -0,0 +1,416 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# U-Boot 2016.01-rc3 Configuration
+#
+CONFIG_HAVE_GENERIC_BOARD=y
+CONFIG_SYS_GENERIC_BOARD=y
+# CONFIG_ARC is not set
+# CONFIG_ARM is not set
+# CONFIG_AVR32 is not set
+# CONFIG_BLACKFIN is not set
+# CONFIG_M68K is not set
+# CONFIG_MICROBLAZE is not set
+CONFIG_MIPS=y
+# CONFIG_NDS32 is not set
+# CONFIG_NIOS2 is not set
+# CONFIG_OPENRISC is not set
+# CONFIG_PPC is not set
+# CONFIG_SANDBOX is not set
+# CONFIG_SH is not set
+# CONFIG_SPARC is not set
+# CONFIG_X86 is not set
+CONFIG_SYS_ARCH="mips"
+CONFIG_SYS_CPU="mips32"
+CONFIG_SYS_SOC="pic32mzda"
+CONFIG_SYS_VENDOR="microchip"
+CONFIG_SYS_BOARD="pic32mzda"
+CONFIG_SYS_CONFIG_NAME="pic32mzdask"
+CONFIG_SYS_MALLOC_F_LEN=0x600
+CONFIG_SYS_MALLOC_F=y
+CONFIG_DM_SERIAL=y
+# CONFIG_DM_SPI is not set
+# CONFIG_DM_I2C is not set
+CONFIG_DM_GPIO=y
+
+#
+# MIPS architecture
+#
+# CONFIG_TARGET_QEMU_MIPS is not set
+# CONFIG_TARGET_MALTA is not set
+# CONFIG_TARGET_VCT is not set
+# CONFIG_TARGET_DBAU1X00 is not set
+# CONFIG_TARGET_PB1X00 is not set
+CONFIG_MACH_PIC32=y
+
+#
+# Microchip PIC32 platforms
+#
+CONFIG_SOC_PIC32MZDA=y
+CONFIG_TARGET_PIC32MZDASK=y
+CONFIG_SYS_LITTLE_ENDIAN=y
+# CONFIG_CPU_MIPS32_R1 is not set
+CONFIG_CPU_MIPS32_R2=y
+
+#
+# OS boot interface
+#
+CONFIG_MIPS_BOOT_CMDLINE_LEGACY=y
+# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
+CONFIG_MIPS_BOOT_FDT=y
+CONFIG_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_SUPPORTS_CPU_MIPS32_R1=y
+CONFIG_SUPPORTS_CPU_MIPS32_R2=y
+CONFIG_CPU_MIPS32=y
+CONFIG_32BIT=y
+CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD=y
+CONFIG_MIPS_L1_CACHE_SHIFT_4=y
+CONFIG_MIPS_L1_CACHE_SHIFT=4
+# CONFIG_DM_KEYBOARD is not set
+CONFIG_DEFAULT_DEVICE_TREE="pic32mzda_sk"
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EXPERT=y
+CONFIG_SYS_MALLOC_CLEAR_ON_INIT=y
+
+#
+# Boot images
+#
+# CONFIG_FIT is not set
+CONFIG_SYS_EXTRA_OPTIONS=""
+
+#
+# Command line interface
+#
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="dask # "
+
+#
+# Autoboot options
+#
+# CONFIG_AUTOBOOT_KEYED is not set
+
+#
+# Commands
+#
+
+#
+# Info commands
+#
+CONFIG_CMD_BDI=y
+CONFIG_CMD_CONSOLE=y
+# CONFIG_CMD_CPU is not set
+# CONFIG_CMD_LICENSE is not set
+
+#
+# Boot commands
+#
+CONFIG_CMD_BOOTD=y
+CONFIG_CMD_BOOTM=y
+CONFIG_CMD_ELF=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_RUN=y
+CONFIG_CMD_IMI=y
+# CONFIG_CMD_IMLS is not set
+CONFIG_CMD_XIMG=y
+
+#
+# Environment commands
+#
+# CONFIG_CMD_EXPORTENV is not set
+CONFIG_CMD_IMPORTENV=y
+CONFIG_CMD_EDITENV=y
+# CONFIG_CMD_SAVEENV is not set
+CONFIG_CMD_ENV_EXISTS=y
+
+#
+# Memory commands
+#
+CONFIG_CMD_MEMORY=y
+CONFIG_CMD_CRC32=y
+CONFIG_LOOPW=y
+CONFIG_CMD_MEMTEST=y
+# CONFIG_CMD_MX_CYCLIC is not set
+CONFIG_CMD_MEMINFO=y
+
+#
+# Device access commands
+#
+CONFIG_CMD_DM=y
+# CONFIG_CMD_DEMO is not set
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_LOADS=y
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_NAND is not set
+# CONFIG_CMD_SF is not set
+# CONFIG_CMD_SPI is not set
+# CONFIG_CMD_I2C is not set
+# CONFIG_CMD_USB is not set
+# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_GPIO=y
+
+#
+# Shell scripting commands
+#
+CONFIG_CMD_ECHO=y
+CONFIG_CMD_ITEST=y
+CONFIG_CMD_SOURCE=y
+CONFIG_CMD_SETEXPR=y
+
+#
+# Network commands
+#
+# CONFIG_CMD_NET is not set
+# CONFIG_CMD_TFTPPUT is not set
+# CONFIG_CMD_TFTPSRV is not set
+# CONFIG_CMD_RARP is not set
+# CONFIG_CMD_DHCP is not set
+# CONFIG_CMD_NFS is not set
+# CONFIG_CMD_PING is not set
+# CONFIG_CMD_CDP is not set
+# CONFIG_CMD_SNTP is not set
+# CONFIG_CMD_DNS is not set
+# CONFIG_CMD_LINK_LOCAL is not set
+
+#
+# Misc commands
+#
+CONFIG_CMD_TIME=y
+CONFIG_CMD_MISC=y
+# CONFIG_CMD_TIMER is not set
+
+#
+# Boot timing
+#
+# CONFIG_BOOTSTAGE is not set
+CONFIG_BOOTSTAGE_USER_COUNT=20
+CONFIG_BOOTSTAGE_STASH_ADDR=0
+CONFIG_BOOTSTAGE_STASH_SIZE=4096
+
+#
+# Power commands
+#
+
+#
+# Security commands
+#
+# CONFIG_CONSOLE_RECORD is not set
+CONFIG_SUPPORT_OF_CONTROL=y
+
+#
+# Device Tree Control
+#
+CONFIG_OF_CONTROL=y
+# CONFIG_OF_SEPARATE is not set
+CONFIG_OF_EMBED=y
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_DM=y
+CONFIG_DM_WARN=y
+CONFIG_DM_DEVICE_REMOVE=y
+CONFIG_DM_STDIO=y
+CONFIG_DM_SEQ_ALIAS=y
+# CONFIG_REGMAP is not set
+# CONFIG_SPL_REGMAP is not set
+# CONFIG_DEVRES is not set
+CONFIG_SIMPLE_BUS=y
+CONFIG_OF_TRANSLATE=y
+# CONFIG_ADC is not set
+# CONFIG_ADC_EXYNOS is not set
+# CONFIG_ADC_SANDBOX is not set
+CONFIG_CLK=y
+# CONFIG_SPL_CLK is not set
+# CONFIG_CPU is not set
+
+#
+# Hardware crypto devices
+#
+# CONFIG_FSL_CAAM is not set
+
+#
+# Demo for driver model
+#
+# CONFIG_DM_DEMO is not set
+
+#
+# DFU support
+#
+# CONFIG_DFU_TFTP is not set
+
+#
+# GPIO Support
+#
+# CONFIG_ALTERA_PIO is not set
+# CONFIG_DWAPB_GPIO is not set
+# CONFIG_ATMEL_PIO4 is not set
+# CONFIG_LPC32XX_GPIO is not set
+# CONFIG_ROCKCHIP_GPIO is not set
+# CONFIG_VYBRID_GPIO is not set
+CONFIG_PIC32_GPIO=y
+
+#
+# I2C support
+#
+# CONFIG_DM_I2C_COMPAT is not set
+# CONFIG_CROS_EC_KEYB is not set
+
+#
+# LED Support
+#
+# CONFIG_LED is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MISC is not set
+# CONFIG_CROS_EC is not set
+# CONFIG_FSL_SEC_MON is not set
+# CONFIG_MXC_OCOTP is not set
+# CONFIG_PCA9551_LED is not set
+# CONFIG_RESET is not set
+
+#
+# MMC Host controller Support
+#
+# CONFIG_DM_MMC is not set
+
+#
+# MTD Support
+#
+# CONFIG_MTD is not set
+
+#
+# NAND Device Support
+#
+# CONFIG_NAND_DENALI is not set
+# CONFIG_NAND_VF610_NFC is not set
+# CONFIG_NAND_PXA3XX is not set
+
+#
+# Generic NAND options
+#
+
+#
+# SPI Flash Support
+#
+# CONFIG_SPI_FLASH is not set
+# CONFIG_DM_ETH is not set
+# CONFIG_PHYLIB is not set
+
+#
+# PCI
+#
+# CONFIG_DM_PCI is not set
+
+#
+# Pin controllers
+#
+CONFIG_PINCTRL=y
+# CONFIG_PINCTRL_FULL is not set
+# CONFIG_ROCKCHIP_PINCTRL is not set
+# CONFIG_ROCKCHIP_3036_PINCTRL is not set
+CONFIG_PIC32_PINCTRL=y
+
+#
+# Power
+#
+# CONFIG_DM_PMIC is not set
+# CONFIG_DM_REGULATOR is not set
+# CONFIG_RAM is not set
+
+#
+# Remote Processor drivers
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_DM_RTC is not set
+
+#
+# Serial drivers
+#
+CONFIG_REQUIRE_SERIAL_CONSOLE=y
+# CONFIG_DEBUG_UART is not set
+# CONFIG_ALTERA_JTAG_UART is not set
+# CONFIG_ALTERA_UART is not set
+# CONFIG_SYS_NS16550 is not set
+CONFIG_PIC32_SERIAL=y
+
+#
+# Sound support
+#
+# CONFIG_SOUND is not set
+
+#
+# SPI Support
+#
+# CONFIG_FSL_ESPI is not set
+# CONFIG_TI_QSPI is not set
+# CONFIG_DM_THERMAL is not set
+
+#
+# Timer Support
+#
+# CONFIG_TIMER is not set
+
+#
+# TPM support
+#
+# CONFIG_USB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VIDEO_VESA is not set
+# CONFIG_VIDEO_LCD_ANX9804 is not set
+# CONFIG_VIDEO_LCD_SSD2828 is not set
+# CONFIG_DISPLAY_PORT is not set
+# CONFIG_VIDEO_TEGRA124 is not set
+# CONFIG_VIDEO_BRIDGE is not set
+# CONFIG_PHYS_TO_BUS is not set
+
+#
+# File systems
+#
+
+#
+# Library routines
+#
+# CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED is not set
+CONFIG_HAVE_PRIVATE_LIBGCC=y
+# CONFIG_USE_PRIVATE_LIBGCC is not set
+CONFIG_SYS_HZ=1000
+CONFIG_SYS_VSNPRINTF=y
+CONFIG_USE_TINY_PRINTF=y
+CONFIG_REGEX=y
+# CONFIG_LIB_RAND is not set
+CONFIG_CMD_DHRYSTONE=y
+# CONFIG_RSA is not set
+# CONFIG_TPM is not set
+
+#
+# Hashing Support
+#
+# CONFIG_SHA1 is not set
+# CONFIG_SHA256 is not set
+# CONFIG_SHA_HW_ACCEL is not set
+
+#
+# Compression Support
+#
+# CONFIG_LZ4 is not set
+# CONFIG_ERRNO_STR is not set
+# CONFIG_UNIT_TEST is not set
diff --git a/include/configs/pic32mzdask.h b/include/configs/pic32mzdask.h
new file mode 100644
index 0000000..6552fa2
--- /dev/null
+++ b/include/configs/pic32mzdask.h
@@ -0,0 +1,94 @@
+/*
+ * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ * Microchip PIC32MZ[DA] Starter Kit.
+ */
+
+#ifndef __PIC32MZDASK_CONFIG_H
+#define __PIC32MZDASK_CONFIG_H
+
+/* System Configuration */
+#define CONFIG_SYS_TEXT_BASE		0x9d004000 /* .text */
+#define CONFIG_DISPLAY_BOARDINFO
+
+/*--------------------------------------------
+ * CPU configuration
+ */
+/* CPU Timer rate */
+#define CONFIG_SYS_MIPS_TIMER_FREQ	100000000
+
+/* Cache Configuration */
+#define CONFIG_SYS_MIPS_CACHE_MODE	CONF_CM_CACHABLE_NONCOHERENT
+
+/*----------------------------------------------------------------------
+ * Memory Layout
+ */
+#define CONFIG_SYS_SRAM_BASE		0x80000000
+#define CONFIG_SYS_SRAM_SIZE		0x00080000 /* 512K */
+
+/* Initial RAM for temporary stack, global data */
+#define CONFIG_SYS_INIT_RAM_SIZE	0x10000
+#define CONFIG_SYS_INIT_RAM_ADDR	\
+	(CONFIG_SYS_SRAM_BASE + CONFIG_SYS_SRAM_SIZE - CONFIG_SYS_INIT_RAM_SIZE)
+#define CONFIG_SYS_INIT_SP_ADDR		\
+	(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE - 1)
+
+/* SDRAM Configuration (for final code, data, stack, heap) */
+#define CONFIG_SYS_SDRAM_BASE		0x88000000
+#define CONFIG_SYS_MALLOC_LEN		(256 << 10)
+#define CONFIG_SYS_BOOTPARAMS_LEN	(4 << 10)
+#define CONFIG_STACKSIZE		(4 << 10) /* regular stack */
+
+#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE
+#define CONFIG_SYS_MONITOR_LEN		(192 << 10)
+
+#define CONFIG_SYS_LOAD_ADDR		0x88500000 /* default load address */
+#define CONFIG_SYS_ENV_ADDR		0x88300000
+
+/* Memory Test */
+#define CONFIG_SYS_MEMTEST_START	0x88000000
+#define CONFIG_SYS_MEMTEST_END		0x88080000
+
+/*----------------------------------------------------------------------
+ * Commands
+ */
+#define CONFIG_SYS_LONGHELP		/* undef to save memory */
+#define CONFIG_CMD_CLK
+
+/*-------------------------------------------------
+ * FLASH configuration
+ */
+#define CONFIG_SYS_NO_FLASH
+
+/*------------------------------------------------------------
+ * Console Configuration
+ */
+#define CONFIG_BAUDRATE			115200
+#define CONFIG_SYS_BAUDRATE_TABLE	{9600, 19200, 38400, 57600, 115200}
+#define CONFIG_SYS_CBSIZE		1024 /* Console I/O Buffer Size   */
+#define CONFIG_SYS_MAXARGS		16   /* max number of command args*/
+#define CONFIG_SYS_PBSIZE		\
+		(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_CMDLINE_EDITING		1
+
+/*
+ * Handover flattened device tree (dtb file) to Linux kernel
+ */
+#define CONFIG_OF_LIBFDT	1
+
+/* -------------------------------------------------
+ * Environment
+ */
+#define CONFIG_ENV_IS_NOWHERE	1
+#define CONFIG_ENV_SIZE		0x4000
+
+/* ---------------------------------------------------------------------
+ * Board boot configuration
+ */
+#define CONFIG_TIMESTAMP	/* Print image info with timestamp */
+#define CONFIG_BOOTDELAY	5 /* autoboot after X seconds     */
+#undef	CONFIG_BOOTARGS
+
+#endif	/* __PIC32MZDASK_CONFIG_H */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 10/14] drivers: mmc: add driver for Microchip PIC32 SDHCI controller.
  2016-01-12 10:18 [U-Boot] [PATCH v3 00/14] Initial Microchip PIC32MZ[DA] Support Purna Chandra Mandal
                   ` (8 preceding siblings ...)
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 09/14] board: Add Microchip PIC32MZ[DA]-Starter-Kit board Purna Chandra Mandal
@ 2016-01-12 10:18 ` Purna Chandra Mandal
  2016-01-13 14:56   ` Tom Rini
  2016-01-13 15:15   ` Daniel Schwierzeck
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 11/14] board: add SDHCI support for PIC32MZDASK board Purna Chandra Mandal
                   ` (3 subsequent siblings)
  13 siblings, 2 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-12 10:18 UTC (permalink / raw)
  To: u-boot

From: Andrei Pistirica <andrei.pistirica@microchip.com>

This driver implements platform specific glue and fixups for
PIC32 internal SDHCI controller.

Signed-off-by: Andrei Pistirica <andrei.pistirica@microchip.com>
Signed-off-by: Sandeep Sheriker Mallikarjun <sandeepsheriker.mallikarjun@microchip.com>
Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>

---

Changes in v3:
- remove ofdata_to_platdata, and replace platdata with priv
- replace pic32_ioremap() with ioremap()

Changes in v2:
- drop sdhci shared bus configuration (for shared interrupt, clock pins)

 drivers/mmc/Kconfig       |  6 +++++
 drivers/mmc/Makefile      |  2 +-
 drivers/mmc/pic32_sdhci.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/mmc/sdhci.c       | 12 ++++++++++
 4 files changed, 80 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mmc/pic32_sdhci.c

diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index ceae7bc..0b6f54b 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -31,4 +31,10 @@ config SH_SDHI
 	help
 	  Support for the on-chip SDHI host controller on SuperH/Renesas ARM SoCs platform
 
+config PIC32_SDHCI
+	bool "Microchip PIC32 on-chip SDHCI support"
+	depends on DM_MMC && MACH_PIC32
+	help
+	  Support for the on-chip SDHCI support on Microchip PIC32 platforms.
+
 endmenu
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 5d35705..c9c3e3e 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -48,4 +48,4 @@ obj-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o
 else
 obj-$(CONFIG_GENERIC_MMC) += mmc_write.o
 endif
-
+obj-$(CONFIG_PIC32_SDHCI) += pic32_sdhci.o
diff --git a/drivers/mmc/pic32_sdhci.c b/drivers/mmc/pic32_sdhci.c
new file mode 100644
index 0000000..f8a5a23
--- /dev/null
+++ b/drivers/mmc/pic32_sdhci.c
@@ -0,0 +1,61 @@
+/*
+ * Support of SDHCI for Microchip PIC32 SoC.
+ *
+ * Copyright (C) 2015 Microchip Technology Inc.
+ * Andrei Pistirica <andrei.pistirica@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <dm.h>
+#include <common.h>
+#include <sdhci.h>
+#include <asm/errno.h>
+#include <mach/pic32.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int pic32_sdhci_probe(struct udevice *dev)
+{
+	struct sdhci_host *host = dev_get_priv(dev);
+	const void *fdt = gd->fdt_blob;
+	u32 f_min_max[2];
+	fdt_addr_t addr;
+	fdt_size_t size;
+	int ret;
+
+	addr = fdtdec_get_addr_size(fdt, dev->of_offset, "reg", &size);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	host->ioaddr = ioremap(addr, size);
+	if (!host->ioaddr)
+		return -EINVAL;
+
+	host->name	= (char *)dev->name;
+	host->quirks	= SDHCI_QUIRK_NO_HISPD_BIT;
+	host->bus_width	= fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+					"bus-width", 4);
+
+	ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
+				   "clock-freq-min-max", f_min_max, 2);
+	if (ret) {
+		printf("sdhci: clock-freq-min-max not found\n");
+		return ret;
+	}
+
+	return add_sdhci(host, f_min_max[1], f_min_max[0]);
+}
+
+static const struct udevice_id pic32_sdhci_ids[] = {
+	{ .compatible = "microchip,pic32mzda-sdhci" },
+	{ }
+};
+
+U_BOOT_DRIVER(pic32_sdhci_drv) = {
+	.name			= "pic32_sdhci",
+	.id			= UCLASS_MMC,
+	.of_match		= pic32_sdhci_ids,
+	.probe			= pic32_sdhci_probe,
+	.priv_auto_alloc_size	= sizeof(struct sdhci_host),
+};
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 02d71b9..f32fe67 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -424,6 +424,18 @@ static void sdhci_set_ios(struct mmc *mmc)
 	if (host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)
 		ctrl &= ~SDHCI_CTRL_HISPD;
 
+#if defined(CONFIG_PIC32_SDHCI)
+	/*
+	* In PIC32MZ[DA] due to h/w bug SDHCI fails detecting card when JTAG
+	* is not connected.
+	* To work-around this problem:
+	*  - set Card_Detect_Signal_Selection bit in SDHCI_Host_Control register
+	*  - clear Card_Detect_Test_Level bit in SDHCI_Host_Control register
+	*/
+	ctrl |= SDHCI_CTRL_CD_TEST;
+	ctrl &= ~SDHCI_CTRL_CD_TEST_INS;
+#endif
+
 	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 }
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 11/14] board: add SDHCI support for PIC32MZDASK board.
  2016-01-12 10:18 [U-Boot] [PATCH v3 00/14] Initial Microchip PIC32MZ[DA] Support Purna Chandra Mandal
                   ` (9 preceding siblings ...)
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 10/14] drivers: mmc: add driver for Microchip PIC32 SDHCI controller Purna Chandra Mandal
@ 2016-01-12 10:18 ` Purna Chandra Mandal
  2016-01-13 14:56   ` Tom Rini
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 12/14] drivers: net: phy: add SMSC LAN8740 Phy support Purna Chandra Mandal
                   ` (2 subsequent siblings)
  13 siblings, 1 reply; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-12 10:18 UTC (permalink / raw)
  To: u-boot

Enable MMC, SDHCI, FAT FS, EXT4 FS support for PIC32MZ[DA] StarterKit.
Also add custom scripts, rules to boot Linux from microSD card.

Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>

---

Changes in v3: None
Changes in v2:
- drop shared bus (shared pin selection) configuration.

 arch/mips/dts/pic32mzda.dtsi   | 11 ++++++++
 arch/mips/dts/pic32mzda_sk.dts |  7 +++++
 configs/pic32mzdask_defconfig  |  6 +++--
 include/configs/pic32mzdask.h  | 61 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 83 insertions(+), 2 deletions(-)

diff --git a/arch/mips/dts/pic32mzda.dtsi b/arch/mips/dts/pic32mzda.dtsi
index fe8b13a..3d62a17 100644
--- a/arch/mips/dts/pic32mzda.dtsi
+++ b/arch/mips/dts/pic32mzda.dtsi
@@ -150,4 +150,15 @@
 			#gpio-cells = <2>;
 		};
 	};
+
+	sdhci: sdhci at 1f8ec000 {
+		compatible = "microchip,pic32mzda-sdhci";
+		reg = <0x1f8ec000 0x100>;
+		interrupts = <191 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&clock REF4CLK>, <&clock PB5CLK>;
+		clock-names = "base_clk", "sys_clk";
+		clock-freq-min-max = <25000000>,<25000000>;
+		bus-width = <4>;
+		status = "disabled";
+	};
 };
diff --git a/arch/mips/dts/pic32mzda_sk.dts b/arch/mips/dts/pic32mzda_sk.dts
index 99e7f64..f886a0f 100644
--- a/arch/mips/dts/pic32mzda_sk.dts
+++ b/arch/mips/dts/pic32mzda_sk.dts
@@ -23,6 +23,9 @@
 };
 
 &clock {
+	microchip,refo2-frequency = <50000000>;
+	microchip,refo4-frequency = <25000000>;
+	microchip,refo5-frequency = <40000000>;
 	status = "okay";
 	u-boot,dm-pre-reloc;
 };
@@ -36,3 +39,7 @@
 	status = "okay";
 	u-boot,dm-pre-reloc;
 };
+
+&sdhci {
+	status = "okay";
+};
\ No newline at end of file
diff --git a/configs/pic32mzdask_defconfig b/configs/pic32mzdask_defconfig
index 3483eb0..6981cf7 100644
--- a/configs/pic32mzdask_defconfig
+++ b/configs/pic32mzdask_defconfig
@@ -122,7 +122,7 @@ CONFIG_CMD_XIMG=y
 #
 # Environment commands
 #
-# CONFIG_CMD_EXPORTENV is not set
+CONFIG_CMD_EXPORTENV=y
 CONFIG_CMD_IMPORTENV=y
 CONFIG_CMD_EDITENV=y
 # CONFIG_CMD_SAVEENV is not set
@@ -284,7 +284,9 @@ CONFIG_PIC32_GPIO=y
 #
 # MMC Host controller Support
 #
-# CONFIG_DM_MMC is not set
+CONFIG_DM_MMC=y
+# CONFIG_ROCKCHIP_DWMMC is not set
+CONFIG_PIC32_SDHCI=y
 
 #
 # MTD Support
diff --git a/include/configs/pic32mzdask.h b/include/configs/pic32mzdask.h
index 6552fa2..224b21c 100644
--- a/include/configs/pic32mzdask.h
+++ b/include/configs/pic32mzdask.h
@@ -78,6 +78,33 @@
  */
 #define CONFIG_OF_LIBFDT	1
 
+/*-----------------------------------------------------------------------
+ * SDHC Configuration
+ */
+#define CONFIG_SDHCI
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_CMD_MMC
+
+/*-----------------------------------------------------------------------
+ * File System Configuration
+ */
+/* FAT FS */
+#define CONFIG_DOS_PARTITION
+#define CONFIG_PARTITION_UUIDS
+#define CONFIG_SUPPORT_VFAT
+#define CONFIG_FS_FAT
+#define CONFIG_FAT_WRITE
+#define CONFIG_CMD_FS_GENERIC
+#define CONFIG_CMD_PART
+#define CONFIG_CMD_FAT
+
+/* EXT4 FS */
+#define CONFIG_FS_EXT4
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_EXT4
+#define CONFIG_CMD_EXT4_WRITE
+
 /* -------------------------------------------------
  * Environment
  */
@@ -91,4 +118,38 @@
 #define CONFIG_BOOTDELAY	5 /* autoboot after X seconds     */
 #undef	CONFIG_BOOTARGS
 
+#define CONFIG_EXTRA_ENV_SETTINGS				\
+	"loadaddr="__stringify(CONFIG_SYS_LOAD_ADDR)"\0"	\
+	"uenvfile=uEnv.txt\0"					\
+	"uenvaddr="__stringify(CONFIG_SYS_ENV_ADDR)"\0"		\
+	"scriptfile=boot.scr\0"					\
+	"ubootfile=u-boot.bin\0"				\
+	"importbootenv= "					\
+		"env import -t -r ${uenvaddr} ${filesize};\0"	\
+								\
+	"mmcloadenv=fatload mmc 0 ${uenvaddr} ${uenvfile}\0"	\
+	"mmcloadscr=fatload mmc 0 ${uenvaddr} ${scriptfile}\0"	\
+	"mmcloadub=fatload mmc 0 ${loadaddr} ${ubootfile}\0"	\
+								\
+	"loadbootenv=run mmcloadenv\0"				\
+	"loadbootscr=run mmcloadscr\0"				\
+	"bootcmd_root= "					\
+		"if run loadbootenv; then "			\
+			"echo Loaded environment ${uenvfile}; "	\
+			"run importbootenv; "			\
+		"fi; "						\
+		"if test -n \"${bootcmd_uenv}\" ; then "	\
+			"echo Running bootcmd_uenv ...; "	\
+			"run bootcmd_uenv; "			\
+		"fi; "						\
+		"if run loadbootscr; then "			\
+			"echo Jumping to ${scriptfile}; "	\
+			"source ${uenvaddr}; "			\
+		"fi; "						\
+		"echo Custom environment or script not found. "	\
+			"Aborting auto booting...; \0"		\
+	""
+
+#define CONFIG_BOOTCOMMAND		"run bootcmd_root"
+
 #endif	/* __PIC32MZDASK_CONFIG_H */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 12/14] drivers: net: phy: add SMSC LAN8740 Phy support.
  2016-01-12 10:18 [U-Boot] [PATCH v3 00/14] Initial Microchip PIC32MZ[DA] Support Purna Chandra Mandal
                   ` (10 preceding siblings ...)
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 11/14] board: add SDHCI support for PIC32MZDASK board Purna Chandra Mandal
@ 2016-01-12 10:18 ` Purna Chandra Mandal
  2016-01-13 14:56   ` Tom Rini
  2016-01-13 15:19   ` Daniel Schwierzeck
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 13/14] drivers: net: Add ethernet driver for Microchip PIC32 Purna Chandra Mandal
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 14/14] board: Enable ethernet, tftpboot support to pic32mzdask board Purna Chandra Mandal
  13 siblings, 2 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-12 10:18 UTC (permalink / raw)
  To: u-boot

Add SMSC LAN8740 Phy support required for PIC32MZDA devices.

Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>

---

Changes in v3: None
Changes in v2: None

 drivers/net/phy/smsc.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index bfd9815..34986a2 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -69,11 +69,21 @@ static struct phy_driver lan8710_driver = {
 	.shutdown = &genphy_shutdown,
 };
 
+static struct phy_driver lan8740_driver = {
+	.name = "SMSC LAN8740",
+	.uid = 0x0007c110,
+	.mask = 0xffff0,
+	.features = PHY_BASIC_FEATURES,
+	.config = &genphy_config_aneg,
+	.startup = &genphy_startup,
+	.shutdown = &genphy_shutdown,
+};
 int phy_smsc_init(void)
 {
 	phy_register(&lan8710_driver);
 	phy_register(&lan911x_driver);
 	phy_register(&lan8700_driver);
+	phy_register(&lan8740_driver);
 
 	return 0;
 }
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 13/14] drivers: net: Add ethernet driver for Microchip PIC32.
  2016-01-12 10:18 [U-Boot] [PATCH v3 00/14] Initial Microchip PIC32MZ[DA] Support Purna Chandra Mandal
                   ` (11 preceding siblings ...)
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 12/14] drivers: net: phy: add SMSC LAN8740 Phy support Purna Chandra Mandal
@ 2016-01-12 10:18 ` Purna Chandra Mandal
  2016-01-13 14:56   ` Tom Rini
  2016-01-13 15:37   ` Daniel Schwierzeck
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 14/14] board: Enable ethernet, tftpboot support to pic32mzdask board Purna Chandra Mandal
  13 siblings, 2 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-12 10:18 UTC (permalink / raw)
  To: u-boot

This driver implements MAC and MII layer of the ethernet controller.
Network data transfer is handled by controller internal DMA engine.
Ethernet controller is configurable through device-tree file.

Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>


---

Changes in v3:
- merge wrappers with eth operation callbacks
- read phy address from device-tree
- rename functions (e.g. _eth_xyz() with pic32_eth_xyz())

Changes in v2: None

 drivers/net/Kconfig      |   7 +
 drivers/net/Makefile     |   1 +
 drivers/net/pic32_eth.c  | 606 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/pic32_eth.h  | 171 +++++++++++++
 drivers/net/pic32_mdio.c | 121 ++++++++++
 5 files changed, 906 insertions(+)
 create mode 100644 drivers/net/pic32_eth.c
 create mode 100644 drivers/net/pic32_eth.h
 create mode 100644 drivers/net/pic32_mdio.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index ae5e78d..dc49493 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -108,4 +108,11 @@ config ZYNQ_GEM
 	help
 	  This MAC is present in Xilinx Zynq and ZynqMP SoCs.
 
+config PIC32_ETH
+	bool "Microchip PIC32 Ethernet Support"
+	depends on MACH_PIC32
+	help
+	  This driver implements 10/100 Mbps Ethernet and MAC layer for
+	  Microchip PIC32 microcontrollers.
+
 endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 150470c..33a81ee 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -72,3 +72,4 @@ obj-$(CONFIG_FSL_MC_ENET) += fsl-mc/
 obj-$(CONFIG_FSL_MC_ENET) += ldpaa_eth/
 obj-$(CONFIG_FSL_MEMAC) += fm/memac_phy.o
 obj-$(CONFIG_VSC9953) += vsc9953.o
+obj-$(CONFIG_PIC32_ETH) += pic32_mdio.o pic32_eth.o
diff --git a/drivers/net/pic32_eth.c b/drivers/net/pic32_eth.c
new file mode 100644
index 0000000..1cef62e
--- /dev/null
+++ b/drivers/net/pic32_eth.c
@@ -0,0 +1,606 @@
+/*
+ * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ */
+#include <common.h>
+#include <errno.h>
+#include <dm.h>
+#include <net.h>
+#include <miiphy.h>
+#include <console.h>
+#include <wait_bit.h>
+#include <asm/gpio.h>
+
+#include "pic32_eth.h"
+
+#define MAX_RX_BUF_SIZE		1536
+#define MAX_RX_DESCR		PKTBUFSRX
+#define MAX_TX_DESCR		2
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct pic32eth_dev {
+	struct eth_dma_desc rxd_ring[MAX_RX_DESCR];
+	struct eth_dma_desc txd_ring[MAX_TX_DESCR];
+	u32 rxd_idx; /* index of RX desc to read */
+	/* regs */
+	struct pic32_ectl_regs *ectl_regs;
+	struct pic32_emac_regs *emac_regs;
+	/* Phy */
+	struct phy_device *phydev;
+	phy_interface_t phyif;
+	u32 phy_addr;
+	struct gpio_desc rst_gpio;
+};
+
+void __weak board_netphy_reset(void *dev)
+{
+	struct pic32eth_dev *priv = (struct pic32eth_dev *)dev;
+
+	if (!dm_gpio_is_valid(&priv->rst_gpio))
+		return;
+
+	/* phy reset */
+	dm_gpio_set_value(&priv->rst_gpio, 0);
+	udelay(300);
+	dm_gpio_set_value(&priv->rst_gpio, 1);
+	udelay(300);
+}
+
+/* Initialize mii(MDIO) interface, discover which PHY is
+ * attached to the device, and configure it properly.
+ */
+static int pic32_mii_init(struct pic32eth_dev *priv)
+{
+	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
+	struct pic32_emac_regs *emac_p = priv->emac_regs;
+
+	/* board phy reset */
+	board_netphy_reset(priv);
+
+	/* disable RX, TX & all transactions */
+	writel(ETHCON_ON | ETHCON_TXRTS | ETHCON_RXEN, &ectl_p->con1.clr);
+
+	/* wait till busy */
+	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY, false,
+		     CONFIG_SYS_HZ, false);
+
+	/* turn controller ON to access PHY over MII */
+	writel(ETHCON_ON, &ectl_p->con1.set);
+
+	mdelay(10);
+
+	/* reset MAC */
+	writel(EMAC_SOFTRESET, &emac_p->cfg1.set); /* reset assert */
+	mdelay(10);
+	writel(EMAC_SOFTRESET, &emac_p->cfg1.clr); /* reset deassert */
+
+	/* initialize MDIO/MII */
+	if (priv->phyif == PHY_INTERFACE_MODE_RMII) {
+		writel(EMAC_RMII_RESET, &emac_p->supp.set);
+		mdelay(10);
+		writel(EMAC_RMII_RESET, &emac_p->supp.clr);
+	}
+
+	return pic32_mdio_init(PIC32_MDIO_NAME, (ulong)&emac_p->mii);
+}
+
+static int pic32_phy_init(struct pic32eth_dev *priv, struct udevice *dev)
+{
+	struct mii_dev *mii;
+
+	mii = miiphy_get_dev_by_name(PIC32_MDIO_NAME);
+
+	/* find & connect PHY */
+	priv->phydev = phy_connect(mii, priv->phy_addr,
+				   dev, priv->phyif);
+	if (!priv->phydev) {
+		printf("%s: %s: Error, PHY connect\n", __FILE__, __func__);
+		return 0;
+	}
+
+	/* Wait for phy to complete reset */
+	mdelay(10);
+
+	/* configure supported modes */
+	priv->phydev->supported = SUPPORTED_10baseT_Half |
+				  SUPPORTED_10baseT_Full |
+				  SUPPORTED_100baseT_Half |
+				  SUPPORTED_100baseT_Full |
+				  SUPPORTED_Autoneg;
+
+	priv->phydev->advertising = ADVERTISED_10baseT_Half |
+				    ADVERTISED_10baseT_Full |
+				    ADVERTISED_100baseT_Half |
+				    ADVERTISED_100baseT_Full |
+				    ADVERTISED_Autoneg;
+
+	priv->phydev->autoneg = AUTONEG_ENABLE;
+
+	return 0;
+}
+
+/* Configure MAC based on negotiated speed and duplex
+ * reported by PHY.
+ */
+static int pic32_mac_adjust_link(struct pic32eth_dev *priv)
+{
+	struct phy_device *phydev = priv->phydev;
+	struct pic32_emac_regs *emac_p = priv->emac_regs;
+
+	if (!phydev->link) {
+		printf("%s: No link.\n", phydev->dev->name);
+		return -EINVAL;
+	}
+
+	if (phydev->duplex) {
+		writel(EMAC_FULLDUP, &emac_p->cfg2.set);
+		writel(FULLDUP_GAP_TIME, &emac_p->ipgt.raw);
+	} else {
+		writel(EMAC_FULLDUP, &emac_p->cfg2.clr);
+		writel(HALFDUP_GAP_TIME, &emac_p->ipgt.raw);
+	}
+
+	switch (phydev->speed) {
+	case SPEED_100:
+		writel(EMAC_RMII_SPD100, &emac_p->supp.set);
+		break;
+	case SPEED_10:
+		writel(EMAC_RMII_SPD100, &emac_p->supp.clr);
+		break;
+	default:
+		printf("%s: Speed was bad\n", phydev->dev->name);
+		return -EINVAL;
+	}
+
+	printf("pic32eth: PHY is %s with %dbase%s, %s\n",
+	       phydev->drv->name, phydev->speed,
+	       (phydev->port == PORT_TP) ? "T" : "X",
+	       (phydev->duplex) ? "full" : "half");
+
+	return 0;
+}
+
+static void pic32_mac_init(struct pic32eth_dev *priv, u8 *macaddr)
+{
+	struct pic32_emac_regs *emac_p = priv->emac_regs;
+	u32 stat = 0, v;
+	u64 expire;
+
+	v = EMAC_TXPAUSE | EMAC_RXPAUSE | EMAC_RXENABLE;
+	writel(v, &emac_p->cfg1.raw);
+
+	v = EMAC_EXCESS | EMAC_AUTOPAD | EMAC_PADENABLE |
+	    EMAC_CRCENABLE | EMAC_LENGTHCK | EMAC_FULLDUP;
+	writel(v, &emac_p->cfg2.raw);
+
+	/* recommended back-to-back inter-packet gap for 10 Mbps half duplex */
+	writel(HALFDUP_GAP_TIME, &emac_p->ipgt.raw);
+
+	/* recommended non-back-to-back interpacket gap is 0xc12 */
+	writel(0xc12, &emac_p->ipgr.raw);
+
+	/* recommended collision window retry limit is 0x370F */
+	writel(0x370f, &emac_p->clrt.raw);
+
+	/* set maximum frame length: allow VLAN tagged frame */
+	writel(0x600, &emac_p->maxf.raw);
+
+	/* set the mac address */
+	writel(macaddr[0] | (macaddr[1] << 8), &emac_p->sa2.raw);
+	writel(macaddr[2] | (macaddr[3] << 8), &emac_p->sa1.raw);
+	writel(macaddr[4] | (macaddr[5] << 8), &emac_p->sa0.raw);
+
+	/* default, enable 10 Mbps operation */
+	writel(EMAC_RMII_SPD100, &emac_p->supp.clr);
+
+	/* wait until link status UP or deadline elapsed */
+	expire = get_ticks() + get_tbclk() * 2;
+	for (; get_ticks() < expire;) {
+		stat = phy_read(priv->phydev, priv->phy_addr, MII_BMSR);
+		if (stat & BMSR_LSTATUS)
+			break;
+	}
+
+	if (!(stat & BMSR_LSTATUS))
+		printf("MAC: Link is DOWN!\n");
+
+	/* delay to stabilize before any tx/rx */
+	mdelay(10);
+}
+
+static void pic32_mac_reset(struct pic32eth_dev *priv)
+{
+	struct pic32_emac_regs *emac_p = priv->emac_regs;
+	struct mii_dev *mii;
+
+	/* Reset MAC */
+	writel(EMAC_SOFTRESET, &emac_p->cfg1.raw);
+	mdelay(10);
+
+	/* clear reset */
+	writel(0, &emac_p->cfg1.raw);
+
+	/* Reset MII */
+	mii = priv->phydev->bus;
+	if (mii && mii->reset)
+		mii->reset(mii);
+}
+
+/* initializes the MAC and PHY, then establishes a link */
+static void pic32_ctrl_reset(struct pic32eth_dev *priv)
+{
+	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
+	u32 v;
+
+	/* disable RX, TX & any other transactions */
+	writel(ETHCON_ON | ETHCON_TXRTS | ETHCON_RXEN, &ectl_p->con1.clr);
+
+	/* wait till busy */
+	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY, false,
+		     CONFIG_SYS_HZ, false);
+	/* decrement received buffcnt to zero. */
+	while (readl(&ectl_p->stat.raw) & ETHSTAT_BUFCNT)
+		writel(ETHCON_BUFCDEC, &ectl_p->con1.set);
+
+	/* clear any existing interrupt event */
+	writel(0xffffffff, &ectl_p->irq.clr);
+
+	/* clear RX/TX start address */
+	writel(0xffffffff, &ectl_p->txst.clr);
+	writel(0xffffffff, &ectl_p->rxst.clr);
+
+	/* clear the receive filters */
+	writel(0x00ff, &ectl_p->rxfc.clr);
+
+	/* set the receive filters
+	 * ETH_FILT_CRC_ERR_REJECT
+	 * ETH_FILT_RUNT_REJECT
+	 * ETH_FILT_UCAST_ACCEPT
+	 * ETH_FILT_MCAST_ACCEPT
+	 * ETH_FILT_BCAST_ACCEPT
+	 */
+	v = ETHRXFC_BCEN | ETHRXFC_MCEN | ETHRXFC_UCEN |
+	    ETHRXFC_RUNTEN | ETHRXFC_CRCOKEN;
+	writel(v, &ectl_p->rxfc.set);
+
+	/* turn controller ON to access PHY over MII */
+	writel(ETHCON_ON, &ectl_p->con1.set);
+}
+
+static void pic32_rx_desc_init(struct pic32eth_dev *priv)
+{
+	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
+	struct eth_dma_desc *rxd;
+	u32 idx, bufsz;
+
+	priv->rxd_idx = 0;
+	for (idx = 0; idx < MAX_RX_DESCR; idx++) {
+		rxd = &priv->rxd_ring[idx];
+
+		/* hw owned */
+		rxd->hdr = EDH_NPV | EDH_EOWN | EDH_STICKY;
+
+		/* packet buffer address */
+		rxd->data_buff = virt_to_phys(net_rx_packets[idx]);
+
+		/* link to next desc */
+		rxd->next_ed = virt_to_phys(rxd + 1);
+
+		/* reset status */
+		rxd->stat1 = 0;
+		rxd->stat2 = 0;
+
+		/* decrement bufcnt */
+		writel(ETHCON_BUFCDEC, &ectl_p->con1.set);
+	}
+
+	/* link last descr to beginning of list */
+	rxd->next_ed = virt_to_phys(&priv->rxd_ring[0]);
+
+	/* flush rx ring */
+	__dcache_flush(priv->rxd_ring, sizeof(priv->rxd_ring));
+
+	/* set rx desc-ring start address */
+	writel((ulong)virt_to_phys(&priv->rxd_ring[0]), &ectl_p->rxst.raw);
+
+	/* RX Buffer size */
+	bufsz = readl(&ectl_p->con2.raw);
+	bufsz &= ~(ETHCON_RXBUFSZ << ETHCON_RXBUFSZ_SHFT);
+	bufsz |= ((MAX_RX_BUF_SIZE / 16) << ETHCON_RXBUFSZ_SHFT);
+	writel(bufsz, &ectl_p->con2.raw);
+
+	/* enable the receiver in hardware which allows hardware
+	 * to DMA received pkts to the descriptor pointer address.
+	 */
+	writel(ETHCON_RXEN, &ectl_p->con1.set);
+}
+
+static int pic32_eth_start(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct pic32eth_dev *priv = dev_get_priv(dev);
+
+	/* controller */
+	pic32_ctrl_reset(priv);
+
+	/* reset MAC */
+	pic32_mac_reset(priv);
+
+	/* configure PHY */
+	phy_config(priv->phydev);
+
+	/* initialize MAC */
+	pic32_mac_init(priv, &pdata->enetaddr[0]);
+
+	/* init RX descriptor; TX descriptors are handled in xmit */
+	pic32_rx_desc_init(priv);
+
+	/* Start up & update link status of PHY */
+	phy_startup(priv->phydev);
+
+	/* adjust mac with phy link status */
+	return pic32_mac_adjust_link(priv);
+}
+
+static void pic32_eth_stop(struct udevice *dev)
+{
+	struct pic32eth_dev *priv = dev_get_priv(dev);
+	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
+	struct pic32_emac_regs *emac_p = priv->emac_regs;
+
+	/* Reset the phy if the controller is enabled */
+	if (readl(&ectl_p->con1.raw) & ETHCON_ON)
+		phy_reset(priv->phydev);
+
+	/* Shut down the PHY */
+	phy_shutdown(priv->phydev);
+
+	/* Stop rx/tx */
+	writel(ETHCON_TXRTS | ETHCON_RXEN, &ectl_p->con1.clr);
+	mdelay(10);
+
+	/* reset MAC */
+	writel(EMAC_SOFTRESET, &emac_p->cfg1.raw);
+
+	/* clear reset */
+	writel(0, &emac_p->cfg1.raw);
+	mdelay(10);
+
+	/* disable controller */
+	writel(ETHCON_ON, &ectl_p->con1.clr);
+	mdelay(10);
+
+	/* wait until everything is down */
+	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY, false,
+		     2 * CONFIG_SYS_HZ, false);
+
+	/* clear any existing interrupt event */
+	writel(0xffffffff, &ectl_p->irq.clr);
+}
+
+static int pic32_eth_send(struct udevice *dev, void *packet, int length)
+{
+	struct pic32eth_dev *priv = dev_get_priv(dev);
+	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
+	struct eth_dma_desc *txd;
+	u64 deadline;
+
+	txd = &priv->txd_ring[0];
+
+	/* set proper flags & length in descriptor header */
+	txd->hdr = EDH_SOP | EDH_EOP | EDH_EOWN | EDH_BCOUNT(length);
+
+	/* pass buffer address to hardware */
+	txd->data_buff = virt_to_phys(packet);
+
+	debug("%s: %d / .hdr %x, .data_buff %x, .stat %x, .nexted %x\n",
+	      __func__, __LINE__, txd->hdr, txd->data_buff, txd->stat2,
+	      txd->next_ed);
+
+	/* cache flush (packet) */
+	__dcache_flush(packet, length);
+
+	/* cache flush (txd) */
+	__dcache_flush(txd, sizeof(*txd));
+
+	/* pass descriptor table base to h/w */
+	writel(virt_to_phys(txd), &ectl_p->txst.raw);
+
+	/* ready to send enabled, hardware can now send the packet(s) */
+	writel(ETHCON_TXRTS | ETHCON_ON, &ectl_p->con1.set);
+
+	/* wait until tx has completed and h/w has released ownership
+	 * of the tx descriptor or timeout elapsed.
+	 */
+	deadline = get_ticks() + get_tbclk();
+	for (;;) {
+		/* check timeout */
+		if (get_ticks() > deadline)
+			return -ETIMEDOUT;
+
+		if (ctrlc())
+			return -EINTR;
+
+		/* tx completed ? */
+		if (readl(&ectl_p->con1.raw) & ETHCON_TXRTS) {
+			udelay(1);
+			continue;
+		}
+
+		/* h/w not released ownership yet? */
+		__dcache_invalidate(txd, sizeof(*txd));
+		if (!(txd->hdr & EDH_EOWN))
+			break;
+	}
+
+	return 0;
+}
+
+static int pic32_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct pic32eth_dev *priv = dev_get_priv(dev);
+	struct eth_dma_desc *rxd;
+	u32 idx = priv->rxd_idx;
+	u32 rx_count;
+
+	/* find the next ready to receive */
+	rxd = &priv->rxd_ring[idx];
+
+	__dcache_invalidate(rxd, sizeof(*rxd));
+	/* check if owned by MAC */
+	if (rxd->hdr & EDH_EOWN)
+		return -EAGAIN;
+
+	/* Sanity check on header: SOP and EOP  */
+	if ((rxd->hdr & (EDH_SOP | EDH_EOP)) != (EDH_SOP | EDH_EOP)) {
+		printf("%s: %s, rx pkt across multiple descr\n",
+		       __FILE__, __func__);
+		return 0;
+	}
+
+	debug("%s: %d /idx %i, hdr=%x, data_buff %x, stat %x, nexted %x\n",
+	      __func__, __LINE__, idx, rxd->hdr,
+	      rxd->data_buff, rxd->stat2, rxd->next_ed);
+
+	/* Sanity check on rx_stat: OK, CRC */
+	if (!RSV_RX_OK(rxd->stat2) || RSV_CRC_ERR(rxd->stat2)) {
+		debug("%s: %s: Error, rx problem detected\n",
+		      __FILE__, __func__);
+		return 0;
+	}
+
+	/* invalidate dcache */
+	rx_count = RSV_RX_COUNT(rxd->stat2);
+	__dcache_invalidate(net_rx_packets[idx], rx_count);
+
+	/* Pass the packet to protocol layer */
+	*packetp = net_rx_packets[idx];
+
+	/* increment number of bytes rcvd (ignore CRC) */
+	return rx_count - 4;
+}
+
+static int pic32_eth_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+	struct pic32eth_dev *priv = dev_get_priv(dev);
+	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
+	struct eth_dma_desc *rxd;
+	int idx = priv->rxd_idx;
+
+	/* sanity check */
+	if (packet != net_rx_packets[idx]) {
+		printf("rxd_id %d: packet is not matched,\n", idx);
+		return -EAGAIN;
+	}
+
+	/* prepare for receive */
+	rxd = &priv->rxd_ring[idx];
+	rxd->hdr = EDH_STICKY | EDH_NPV | EDH_EOWN;
+
+	__dcache_flush(rxd, sizeof(*rxd));
+
+	/* decrement rx pkt count */
+	writel(ETHCON_BUFCDEC, &ectl_p->con1.set);
+
+	debug("%s: %d / idx %i, hdr %x, data_buff %x, stat %x, nexted %x\n",
+	      __func__, __LINE__, idx, rxd->hdr, rxd->data_buff,
+	      rxd->stat2, rxd->next_ed);
+
+	priv->rxd_idx = (priv->rxd_idx + 1) % MAX_RX_DESCR;
+
+	return 0;
+}
+
+static const struct eth_ops pic32_eth_ops = {
+	.start		= pic32_eth_start,
+	.send		= pic32_eth_send,
+	.recv		= pic32_eth_recv,
+	.free_pkt	= pic32_eth_free_pkt,
+	.stop		= pic32_eth_stop,
+};
+
+static int pic32_eth_probe(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct pic32eth_dev *priv = dev_get_priv(dev);
+	const char *phy_mode;
+	void __iomem *iobase;
+	fdt_addr_t addr;
+	fdt_size_t size;
+	int offset = 0;
+	int phy_addr = -1;
+
+	addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg", &size);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	iobase = ioremap(addr, size);
+	if (!iobase)
+		return -EINVAL;
+
+	pdata->iobase = (phys_addr_t)addr;
+
+	/* get phy mode */
+	pdata->phy_interface = -1;
+	phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy-mode", NULL);
+	if (phy_mode)
+		pdata->phy_interface = phy_get_interface_by_name(phy_mode);
+	if (pdata->phy_interface == -1) {
+		debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
+		return -EINVAL;
+	}
+
+	/* get phy addr */
+	offset = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset,
+				       "phy-handle");
+	if (offset > 0)
+		phy_addr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
+
+	/* phy reset gpio */
+	gpio_request_by_name_nodev(gd->fdt_blob, dev->of_offset,
+				   "reset-gpios", 0,
+				   &priv->rst_gpio, GPIOD_IS_OUT);
+
+	priv->phyif	= pdata->phy_interface;
+	priv->phy_addr	= phy_addr;
+	priv->ectl_regs	= iobase;
+	priv->emac_regs	= iobase + PIC32_EMAC1CFG1;
+
+	pic32_mii_init(priv);
+
+	return pic32_phy_init(priv, dev);
+}
+
+static int pic32_eth_remove(struct udevice *dev)
+{
+	struct pic32eth_dev *priv = dev_get_priv(dev);
+	struct mii_dev *bus;
+
+	dm_gpio_free(dev, &priv->rst_gpio);
+	phy_shutdown(priv->phydev);
+	free(priv->phydev);
+	bus = miiphy_get_dev_by_name(PIC32_MDIO_NAME);
+	mdio_unregister(bus);
+	mdio_free(bus);
+	iounmap(priv->ectl_regs);
+	return 0;
+}
+
+static const struct udevice_id pic32_eth_ids[] = {
+	{ .compatible = "microchip,pic32mzda-eth" },
+	{ }
+};
+
+U_BOOT_DRIVER(pic32_ethernet) = {
+	.name			= "pic32_ethernet",
+	.id			= UCLASS_ETH,
+	.of_match		= pic32_eth_ids,
+	.probe			= pic32_eth_probe,
+	.remove			= pic32_eth_remove,
+	.ops			= &pic32_eth_ops,
+	.priv_auto_alloc_size	= sizeof(struct pic32eth_dev),
+	.platdata_auto_alloc_size	= sizeof(struct eth_pdata),
+};
diff --git a/drivers/net/pic32_eth.h b/drivers/net/pic32_eth.h
new file mode 100644
index 0000000..4dd443b
--- /dev/null
+++ b/drivers/net/pic32_eth.h
@@ -0,0 +1,171 @@
+/*
+ * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ */
+
+#ifndef __MICROCHIP_PIC32_ETH_H_
+#define __MICROCHIP_PIC32_ETH_H_
+
+#include <mach/pic32.h>
+
+/* Ethernet */
+struct pic32_ectl_regs {
+	struct pic32_reg_atomic con1; /* 0x00 */
+	struct pic32_reg_atomic con2; /* 0x10 */
+	struct pic32_reg_atomic txst; /* 0x20 */
+	struct pic32_reg_atomic rxst; /* 0x30 */
+	struct pic32_reg_atomic ht0;  /* 0x40 */
+	struct pic32_reg_atomic ht1;  /* 0x50 */
+	struct pic32_reg_atomic pmm0; /* 0x60 */
+	struct pic32_reg_atomic pmm1; /* 0x70 */
+	struct pic32_reg_atomic pmcs; /* 0x80 */
+	struct pic32_reg_atomic pmo;  /* 0x90 */
+	struct pic32_reg_atomic rxfc; /* 0xa0 */
+	struct pic32_reg_atomic rxwm; /* 0xb0 */
+	struct pic32_reg_atomic ien;  /* 0xc0 */
+	struct pic32_reg_atomic irq;  /* 0xd0 */
+	struct pic32_reg_atomic stat; /* 0xe0 */
+};
+
+struct pic32_mii_regs {
+	struct pic32_reg_atomic mcfg; /* 0x280 */
+	struct pic32_reg_atomic mcmd; /* 0x290 */
+	struct pic32_reg_atomic madr; /* 0x2a0 */
+	struct pic32_reg_atomic mwtd; /* 0x2b0 */
+	struct pic32_reg_atomic mrdd; /* 0x2c0 */
+	struct pic32_reg_atomic mind; /* 0x2d0 */
+};
+
+struct pic32_emac_regs {
+	struct pic32_reg_atomic cfg1; /* 0x200*/
+	struct pic32_reg_atomic cfg2; /* 0x210*/
+	struct pic32_reg_atomic ipgt; /* 0x220*/
+	struct pic32_reg_atomic ipgr; /* 0x230*/
+	struct pic32_reg_atomic clrt; /* 0x240*/
+	struct pic32_reg_atomic maxf; /* 0x250*/
+	struct pic32_reg_atomic supp; /* 0x260*/
+	struct pic32_reg_atomic test; /* 0x270*/
+	struct pic32_mii_regs mii;    /* 0x280 - 0x2d0 */
+	struct pic32_reg_atomic res1; /* 0x2e0 */
+	struct pic32_reg_atomic res2; /* 0x2f0 */
+	struct pic32_reg_atomic sa0;  /* 0x300 */
+	struct pic32_reg_atomic sa1;  /* 0x310 */
+	struct pic32_reg_atomic sa2;  /* 0x320 */
+};
+
+/* ETHCON1 Reg field */
+#define ETHCON_BUFCDEC		BIT(0)
+#define ETHCON_RXEN		BIT(8)
+#define ETHCON_TXRTS		BIT(9)
+#define ETHCON_ON		BIT(15)
+
+/* ETHCON2 Reg field */
+#define ETHCON_RXBUFSZ		0x7f
+#define ETHCON_RXBUFSZ_SHFT	0x4
+
+/* ETHSTAT Reg field */
+#define ETHSTAT_BUSY		BIT(7)
+#define ETHSTAT_BUFCNT		0x00ff0000
+
+/* ETHRXFC Register fields */
+#define ETHRXFC_BCEN		BIT(0)
+#define ETHRXFC_MCEN		BIT(1)
+#define ETHRXFC_UCEN		BIT(3)
+#define ETHRXFC_RUNTEN		BIT(4)
+#define ETHRXFC_CRCOKEN		BIT(5)
+
+/* EMAC1CFG1 register offset */
+#define PIC32_EMAC1CFG1		0x0200
+
+/* EMAC1CFG1 register fields */
+#define EMAC_RXENABLE		BIT(0)
+#define EMAC_RXPAUSE		BIT(2)
+#define EMAC_TXPAUSE		BIT(3)
+#define EMAC_SOFTRESET		BIT(15)
+
+/* EMAC1CFG2 register fields */
+#define EMAC_FULLDUP		BIT(0)
+#define EMAC_LENGTHCK		BIT(1)
+#define EMAC_CRCENABLE		BIT(4)
+#define EMAC_PADENABLE		BIT(5)
+#define EMAC_AUTOPAD		BIT(7)
+#define EMAC_EXCESS		BIT(14)
+
+/* EMAC1IPGT register magic */
+#define FULLDUP_GAP_TIME	0x15
+#define HALFDUP_GAP_TIME	0x12
+
+/* EMAC1SUPP register fields */
+#define EMAC_RMII_SPD100	BIT(8)
+#define EMAC_RMII_RESET		BIT(11)
+
+/* MII Management Configuration Register */
+#define MIIMCFG_RSTMGMT		BIT(15)
+#define MIIMCFG_CLKSEL_DIV40	0x0020	/* 100Mhz / 40 */
+
+/* MII Management Command Register */
+#define MIIMCMD_READ		BIT(0)
+#define MIIMCMD_SCAN		BIT(1)
+
+/* MII Management Address Register */
+#define MIIMADD_REGADDR		0x1f
+#define MIIMADD_REGADDR_SHIFT	0
+#define MIIMADD_PHYADDR_SHIFT	8
+
+/* MII Management Indicator Register */
+#define MIIMIND_BUSY		BIT(0)
+#define MIIMIND_NOTVALID	BIT(2)
+#define MIIMIND_LINKFAIL	BIT(3)
+
+/* Packet Descriptor */
+/* Received Packet Status */
+#define _RSV1_PKT_CSUM		0xffff
+#define _RSV2_CRC_ERR		BIT(20)
+#define _RSV2_LEN_ERR		BIT(21)
+#define _RSV2_RX_OK		BIT(23)
+#define _RSV2_RX_COUNT		0xffff
+
+#define RSV_RX_CSUM(__rsv1)	((__rsv1) & _RSV1_PKT_CSUM)
+#define RSV_RX_COUNT(__rsv2)	((__rsv2) & _RSV2_RX_COUNT)
+#define RSV_RX_OK(__rsv2)	((__rsv2) & _RSV2_RX_OK)
+#define RSV_CRC_ERR(__rsv2)	((__rsv2) & _RSV2_CRC_ERR)
+
+/* Ethernet Hardware Descriptor Header bits */
+#define EDH_EOWN		BIT(7)
+#define EDH_NPV			BIT(8)
+#define EDH_STICKY		BIT(9)
+#define _EDH_BCOUNT		0x07ff0000
+#define EDH_EOP			BIT(30)
+#define EDH_SOP			BIT(31)
+#define EDH_BCOUNT_SHIFT	16
+#define EDH_BCOUNT(len)		((len) << EDH_BCOUNT_SHIFT)
+
+/* Ethernet Hardware Descriptors
+ * ref: PIC32 Family Reference Manual Table 35-7
+ * This structure represents the layout of the DMA
+ * memory shared between the CPU and the Ethernet
+ * controller.
+ */
+/* TX/RX DMA descriptor */
+struct eth_dma_desc {
+	u32 hdr;	/* header */
+	u32 data_buff;	/* data buffer address */
+	u32 stat1;	/* transmit/receive packet status */
+	u32 stat2;	/* transmit/receive packet status */
+	u32 next_ed;	/* next descriptor */
+};
+
+/* cache operation helper */
+#define __dcache_flush(__a, __l) \
+	flush_dcache_range((ulong)(__a),  ((__l) + (ulong)(__a)))
+
+#define __dcache_invalidate(__a, __l) \
+	invalidate_dcache_range((ulong)(__a),  ((__l) + (ulong)(__a)))
+
+#define PIC32_MDIO_NAME "PIC32_EMAC"
+
+int pic32_mdio_init(const char *name, ulong ioaddr);
+
+#endif /* __MICROCHIP_PIC32_ETH_H_*/
diff --git a/drivers/net/pic32_mdio.c b/drivers/net/pic32_mdio.c
new file mode 100644
index 0000000..578fc96
--- /dev/null
+++ b/drivers/net/pic32_mdio.c
@@ -0,0 +1,121 @@
+/*
+ * pic32_mdio.c: PIC32 MDIO/MII driver, part of pic32_eth.c.
+ *
+ * Copyright 2015 Microchip Inc.
+ *	Purna Chandra Mandal <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+#include <phy.h>
+#include <miiphy.h>
+#include <errno.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+#include "pic32_eth.h"
+
+static int pic32_mdio_write(struct mii_dev *bus,
+			    int addr, int dev_addr,
+			    int reg, u16 value)
+{
+	u32 v;
+	struct pic32_mii_regs *mii_regs = bus->priv;
+
+	/* Wait for the previous operation to finish */
+	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
+		     false, CONFIG_SYS_HZ, true);
+
+	/* Put phyaddr and regaddr into MIIMADD */
+	v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg & MIIMADD_REGADDR);
+	writel(v, &mii_regs->madr.raw);
+
+	/* Initiate a write command */
+	writel(value, &mii_regs->mwtd.raw);
+
+	/* Wait 30 clock cycles for busy flag to be set */
+	udelay(12);
+
+	/* Wait for write to complete */
+	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
+		     false, CONFIG_SYS_HZ, true);
+
+	return 0;
+}
+
+static int pic32_mdio_read(struct mii_dev *bus, int addr, int devaddr, int reg)
+{
+	u32 v;
+	struct pic32_mii_regs *mii_regs = bus->priv;
+
+	/* Wait for the previous operation to finish */
+	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
+		     false, CONFIG_SYS_HZ, true);
+
+	/* Put phyaddr and regaddr into MIIMADD */
+	v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg & MIIMADD_REGADDR);
+	writel(v, &mii_regs->madr.raw);
+
+	/* Initiate a read command */
+	writel(MIIMCMD_READ, &mii_regs->mcmd.raw);
+
+	/* Wait 30 clock cycles for busy flag to be set */
+	udelay(12);
+
+	/* Wait for read to complete */
+	wait_for_bit(__func__, &mii_regs->mind.raw,
+		     MIIMIND_NOTVALID | MIIMIND_BUSY,
+		     false, CONFIG_SYS_HZ, false);
+
+	/* Clear the command register */
+	writel(0, &mii_regs->mcmd.raw);
+
+	/* Grab the value read from the PHY */
+	v = readl(&mii_regs->mrdd.raw);
+	return v;
+}
+
+static int pic32_mdio_reset(struct mii_dev *bus)
+{
+	struct pic32_mii_regs *mii_regs = bus->priv;
+
+	/* Reset MII (due to new addresses) */
+	writel(MIIMCFG_RSTMGMT, &mii_regs->mcfg.raw);
+
+	/* Wait for the operation to finish */
+	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
+		     false, CONFIG_SYS_HZ, true);
+
+	/* Clear reset bit */
+	writel(0, &mii_regs->mcfg);
+
+	/* Wait for the operation to finish */
+	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
+		     false, CONFIG_SYS_HZ, true);
+
+	/* Set the MII Management Clock (MDC) - no faster than 2.5 MHz */
+	writel(MIIMCFG_CLKSEL_DIV40, &mii_regs->mcfg.raw);
+
+	/* Wait for the operation to finish */
+	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
+		     false, CONFIG_SYS_HZ, true);
+	return 0;
+}
+
+int pic32_mdio_init(const char *name, ulong ioaddr)
+{
+	struct mii_dev *bus;
+
+	bus = mdio_alloc();
+	if (!bus) {
+		printf("Failed to allocate PIC32-MDIO bus\n");
+		return -ENOMEM;
+	}
+
+	bus->read = pic32_mdio_read;
+	bus->write = pic32_mdio_write;
+	bus->reset = pic32_mdio_reset;
+	strncpy(bus->name, name, sizeof(bus->name));
+	bus->priv = (void *)ioaddr;
+
+	return mdio_register(bus);
+}
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 14/14] board: Enable ethernet, tftpboot support to pic32mzdask board.
  2016-01-12 10:18 [U-Boot] [PATCH v3 00/14] Initial Microchip PIC32MZ[DA] Support Purna Chandra Mandal
                   ` (12 preceding siblings ...)
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 13/14] drivers: net: Add ethernet driver for Microchip PIC32 Purna Chandra Mandal
@ 2016-01-12 10:18 ` Purna Chandra Mandal
  2016-01-13 14:56   ` Tom Rini
  13 siblings, 1 reply; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-12 10:18 UTC (permalink / raw)
  To: u-boot

This adds ethernet, TFTP support for PIC32MZ[DA] Starter Kit. Also
custom environment variables/scripts are added to help boot from network.

Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>

---

Changes in v3: None
Changes in v2:
- replace unbounded loop with wait_for_bit()
- replace register access as readl/writel(base + offset)
- translate (dts provided) physical address to MIPS kseg1 address before use

 arch/mips/dts/pic32mzda.dtsi   | 10 ++++++++++
 arch/mips/dts/pic32mzda_sk.dts | 10 ++++++++++
 configs/pic32mzdask_defconfig  | 26 +++++++++++++++++---------
 include/configs/pic32mzdask.h  | 27 +++++++++++++++++++++++++--
 4 files changed, 62 insertions(+), 11 deletions(-)

diff --git a/arch/mips/dts/pic32mzda.dtsi b/arch/mips/dts/pic32mzda.dtsi
index 3d62a17..57612bc 100644
--- a/arch/mips/dts/pic32mzda.dtsi
+++ b/arch/mips/dts/pic32mzda.dtsi
@@ -161,4 +161,14 @@
 		bus-width = <4>;
 		status = "disabled";
 	};
+
+	ethernet: ethernet at 1f882000 {
+		compatible = "microchip,pic32mzda-eth";
+		reg = <0x1f882000 0x1000>;
+		interrupts = <153 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&clock PB5CLK>;
+		status = "disabled";
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
 };
diff --git a/arch/mips/dts/pic32mzda_sk.dts b/arch/mips/dts/pic32mzda_sk.dts
index f886a0f..e5ce0bd 100644
--- a/arch/mips/dts/pic32mzda_sk.dts
+++ b/arch/mips/dts/pic32mzda_sk.dts
@@ -42,4 +42,14 @@
 
 &sdhci {
 	status = "okay";
+};
+
+&ethernet {
+	reset-gpios = <&gpioJ 15 0>;
+	status = "okay";
+	phy-mode = "rmii";
+	phy-handle = <&ethernet_phy>;
+	ethernet_phy: lan8740_phy at 0 {
+		reg = <0>;
+	};
 };
\ No newline at end of file
diff --git a/configs/pic32mzdask_defconfig b/configs/pic32mzdask_defconfig
index 6981cf7..5e78e14 100644
--- a/configs/pic32mzdask_defconfig
+++ b/configs/pic32mzdask_defconfig
@@ -165,13 +165,13 @@ CONFIG_CMD_SETEXPR=y
 #
 # Network commands
 #
-# CONFIG_CMD_NET is not set
+CONFIG_CMD_NET=y
 # CONFIG_CMD_TFTPPUT is not set
 # CONFIG_CMD_TFTPSRV is not set
-# CONFIG_CMD_RARP is not set
-# CONFIG_CMD_DHCP is not set
-# CONFIG_CMD_NFS is not set
-# CONFIG_CMD_PING is not set
+CONFIG_CMD_RARP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_NFS=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_CDP is not set
 # CONFIG_CMD_SNTP is not set
 # CONFIG_CMD_DNS is not set
@@ -208,7 +208,10 @@ CONFIG_SUPPORT_OF_CONTROL=y
 CONFIG_OF_CONTROL=y
 # CONFIG_OF_SEPARATE is not set
 CONFIG_OF_EMBED=y
-# CONFIG_NET is not set
+CONFIG_NET=y
+CONFIG_NET_RANDOM_ETHADDR=y
+# CONFIG_NETCONSOLE is not set
+CONFIG_NET_TFTP_VARS=y
 
 #
 # Device Drivers
@@ -308,8 +311,13 @@ CONFIG_PIC32_SDHCI=y
 # SPI Flash Support
 #
 # CONFIG_SPI_FLASH is not set
-# CONFIG_DM_ETH is not set
-# CONFIG_PHYLIB is not set
+CONFIG_DM_ETH=y
+CONFIG_PHYLIB=y
+CONFIG_NETDEVICES=y
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_E1000 is not set
+# CONFIG_ETH_DESIGNWARE is not set
+CONFIG_PIC32_ETH=y
 
 #
 # PCI
@@ -398,7 +406,7 @@ CONFIG_SYS_HZ=1000
 CONFIG_SYS_VSNPRINTF=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_REGEX=y
-# CONFIG_LIB_RAND is not set
+CONFIG_LIB_RAND=y
 CONFIG_CMD_DHRYSTONE=y
 # CONFIG_RSA is not set
 # CONFIG_TPM is not set
diff --git a/include/configs/pic32mzdask.h b/include/configs/pic32mzdask.h
index 224b21c..7339f0f 100644
--- a/include/configs/pic32mzdask.h
+++ b/include/configs/pic32mzdask.h
@@ -73,6 +73,25 @@
 		(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
 #define CONFIG_CMDLINE_EDITING		1
 
+/*-----------------------------------------------------------------------
+ * Networking Configuration
+ */
+#define CONFIG_MII
+#define CONFIG_PHY_SMSC
+#define CONFIG_SYS_RX_ETH_BUFFER	8
+#define CONFIG_NET_RETRY_COUNT		20
+#define CONFIG_ARP_TIMEOUT		500 /* millisec */
+
+#define CONFIG_CMD_MII
+
+/*
+ * BOOTP options
+ */
+#define CONFIG_BOOTP_BOOTFILESIZE
+#define CONFIG_BOOTP_BOOTPATH
+#define CONFIG_BOOTP_GATEWAY
+#define CONFIG_BOOTP_HOSTNAME
+
 /*
  * Handover flattened device tree (dtb file) to Linux kernel
  */
@@ -127,12 +146,16 @@
 	"importbootenv= "					\
 		"env import -t -r ${uenvaddr} ${filesize};\0"	\
 								\
+	"tftploadenv=tftp ${uenvaddr} ${uenvfile} \0"		\
+	"tftploadscr=tftp ${uenvaddr} ${scriptfile} \0"		\
+	"tftploadub=tftp ${loadaddr} ${ubootfile} \0"		\
+								\
 	"mmcloadenv=fatload mmc 0 ${uenvaddr} ${uenvfile}\0"	\
 	"mmcloadscr=fatload mmc 0 ${uenvaddr} ${scriptfile}\0"	\
 	"mmcloadub=fatload mmc 0 ${loadaddr} ${ubootfile}\0"	\
 								\
-	"loadbootenv=run mmcloadenv\0"				\
-	"loadbootscr=run mmcloadscr\0"				\
+	"loadbootenv=run mmcloadenv || run tftploadenv\0"	\
+	"loadbootscr=run mmcloadscr || run tftploadscr\0"	\
 	"bootcmd_root= "					\
 		"if run loadbootenv; then "			\
 			"echo Loaded environment ${uenvfile}; "	\
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 01/14] MIPS: initialize board_init_f() argument to zero.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 01/14] MIPS: initialize board_init_f() argument to zero Purna Chandra Mandal
@ 2016-01-12 12:29   ` Daniel Schwierzeck
  2016-01-14  5:29     ` Purna Chandra Mandal
  0 siblings, 1 reply; 62+ messages in thread
From: Daniel Schwierzeck @ 2016-01-12 12:29 UTC (permalink / raw)
  To: u-boot

2016-01-12 11:18 GMT+01:00 Purna Chandra Mandal <purna.mandal@microchip.com>:
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/mips/cpu/start.S | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S
> index e95cdca..35d9650 100644
> --- a/arch/mips/cpu/start.S
> +++ b/arch/mips/cpu/start.S
> @@ -185,6 +185,8 @@ reset:
>         PTR_ADDU t0, k0, GD_MALLOC_BASE # gd->malloc_base offset
>         sw      sp, 0(t0)
>  #endif
> +       /* Initialize args to zero */
> +       move    a0, zero

the comment should be on the same line and more precise. That is
useful in disassemblies or when debugging. E.g.

move    a0, zero        # a0 <-- boot_flags = 0

Also add a commit message please explaining why the change is
required. Something like that the boot_flags of board_init_f should be
set to 0 because $a0 may be utilized in lowlevel_init or
mips_cache_reset.

>
>         PTR_LA  t9, board_init_f
>         jr      t9
> --
> 1.8.3.1
>



-- 
- Daniel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 02/14] MIPS: initial infrastructure for Microchip PIC32 architecture
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 02/14] MIPS: initial infrastructure for Microchip PIC32 architecture Purna Chandra Mandal
@ 2016-01-12 12:55   ` Daniel Schwierzeck
  2016-01-13 14:56   ` Tom Rini
  1 sibling, 0 replies; 62+ messages in thread
From: Daniel Schwierzeck @ 2016-01-12 12:55 UTC (permalink / raw)
  To: u-boot

2016-01-12 11:18 GMT+01:00 Purna Chandra Mandal <purna.mandal@microchip.com>:
> Create initial directory, Kconfigs needed for PIC32 architecture
> support. Also add PIC32 specific register definition required for drivers.
>
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>

maybe you could use ioremap() in pic32_get_syscfg_base(), apart from
that it looks good

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

>
> ---
>
> Changes in v3:
> - drop empty choices in mach-pic32/Kconfig
> - add pic32_get_syscfg_base() for device-config registers
>
> Changes in v2:
> - move PIC32 specific headers to arch/mips/mach-pic32/include/mach/
> - define register-base as physical address
> - drop CONFIG_PIC32_SUPPORTS_FDT_BOOT
>
>  arch/mips/Kconfig                         |  6 +++
>  arch/mips/Makefile                        |  1 +
>  arch/mips/mach-pic32/Kconfig              |  7 +++
>  arch/mips/mach-pic32/Makefile             |  7 +++
>  arch/mips/mach-pic32/cpu.c                | 13 ++++++
>  arch/mips/mach-pic32/include/mach/pic32.h | 76 +++++++++++++++++++++++++++++++
>  6 files changed, 110 insertions(+)
>  create mode 100644 arch/mips/mach-pic32/Kconfig
>  create mode 100644 arch/mips/mach-pic32/Makefile
>  create mode 100644 arch/mips/mach-pic32/cpu.c
>  create mode 100644 arch/mips/mach-pic32/include/mach/pic32.h
>
> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> index 1b39c4c..380ed81 100644
> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -54,6 +54,11 @@ config TARGET_PB1X00
>         select SYS_MIPS_CACHE_INIT_RAM_LOAD
>         select MIPS_TUNE_4KC
>
> +config MACH_PIC32
> +       bool "Support Microchip PIC32"
> +       select OF_CONTROL
> +       select DM
> +
>  endchoice
>
>  source "board/dbau1x00/Kconfig"
> @@ -61,6 +66,7 @@ source "board/imgtec/malta/Kconfig"
>  source "board/micronas/vct/Kconfig"
>  source "board/pb1x00/Kconfig"
>  source "board/qemu-mips/Kconfig"
> +source "arch/mips/mach-pic32/Kconfig"
>
>  if MIPS
>
> diff --git a/arch/mips/Makefile b/arch/mips/Makefile
> index 2133e7e..aec5a15 100644
> --- a/arch/mips/Makefile
> +++ b/arch/mips/Makefile
> @@ -8,6 +8,7 @@ libs-y += arch/mips/cpu/
>  libs-y += arch/mips/lib/
>
>  machine-$(CONFIG_SOC_AU1X00) += au1x00
> +machine-$(CONFIG_MACH_PIC32) += pic32
>
>  machdirs := $(patsubst %,arch/mips/mach-%/,$(machine-y))
>  libs-y += $(machdirs)
> diff --git a/arch/mips/mach-pic32/Kconfig b/arch/mips/mach-pic32/Kconfig
> new file mode 100644
> index 0000000..c1cc5e3
> --- /dev/null
> +++ b/arch/mips/mach-pic32/Kconfig
> @@ -0,0 +1,7 @@
> +menu "Microchip PIC32 platforms"
> +       depends on MACH_PIC32
> +
> +config SYS_SOC
> +       default "none"
> +
> +endmenu
> diff --git a/arch/mips/mach-pic32/Makefile b/arch/mips/mach-pic32/Makefile
> new file mode 100644
> index 0000000..cb42607
> --- /dev/null
> +++ b/arch/mips/mach-pic32/Makefile
> @@ -0,0 +1,7 @@
> +# (C) Copyright 2015
> +# Purna Chandra Mandal, purna.mandal at microchip.com.
> +#
> +# SPDX-License-Identifier:      GPL-2.0+
> +#
> +
> +obj-y = cpu.o
> diff --git a/arch/mips/mach-pic32/cpu.c b/arch/mips/mach-pic32/cpu.c
> new file mode 100644
> index 0000000..58fd3ab
> --- /dev/null
> +++ b/arch/mips/mach-pic32/cpu.c
> @@ -0,0 +1,13 @@
> +/*
> + * Copyright (C) 2015
> + * Purna Chandra Mandal <purna.mandal@microchip.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + *
> + */
> +#include <common.h>
> +
> +phys_size_t initdram(int board_type)
> +{
> +       return 0;
> +}
> diff --git a/arch/mips/mach-pic32/include/mach/pic32.h b/arch/mips/mach-pic32/include/mach/pic32.h
> new file mode 100644
> index 0000000..7e41810
> --- /dev/null
> +++ b/arch/mips/mach-pic32/include/mach/pic32.h
> @@ -0,0 +1,76 @@
> +/*
> + * (c) 2015 Paul Thacker <paul.thacker@microchip.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + *
> + */
> +
> +#ifndef __PIC32_REGS_H__
> +#define __PIC32_REGS_H__
> +
> +#include <asm/io.h>
> +
> +/* System Configuration */
> +#define PIC32_CFG_BASE         0x1f800000
> +
> +/* System config register offsets */
> +#define CFGCON         0x0000
> +#define DEVID          0x0020
> +#define SYSKEY         0x0030
> +#define PMD1           0x0040
> +#define PMD7           0x00a0
> +#define CFGEBIA                0x00c0
> +#define CFGEBIC                0x00d0
> +#define CFGPG          0x00e0
> +#define CFGMPLL                0x0100
> +
> +/* Non Volatile Memory (NOR flash) */
> +#define PIC32_NVM_BASE         (PIC32_CFG_BASE + 0x0600)
> +/* Oscillator Configuration */
> +#define PIC32_OSC_BASE         (PIC32_CFG_BASE + 0x1200)
> +/* Peripheral Pin Select Input */
> +#define PPS_IN_BASE            0x1f801400
> +/* Peripheral Pin Select Output */
> +#define PPS_OUT_BASE           0x1f801500
> +/* Pin Config */
> +#define PINCTRL_BASE           0x1f860000
> +
> +/* USB Core */
> +#define PIC32_USB_CORE_BASE    0x1f8e3000
> +#define PIC32_USB_CTRL_BASE    0x1f884000
> +
> +/* SPI1-SPI6 */
> +#define PIC32_SPI1_BASE                0x1f821000
> +
> +/* Prefetch Module */
> +#define PREFETCH_BASE          0x1f8e0000
> +
> +/* DDR2 Controller */
> +#define PIC32_DDR2C_BASE       0x1f8e8000
> +
> +/* DDR2 PHY */
> +#define PIC32_DDR2P_BASE       0x1f8e9100
> +
> +/* EBI */
> +#define PIC32_EBI_BASE         0x1f8e1000
> +
> +/* SQI */
> +#define PIC32_SQI_BASE         0x1f8e2000
> +
> +struct pic32_reg_atomic {
> +       u32 raw;
> +       u32 clr;
> +       u32 set;
> +       u32 inv;
> +};
> +
> +#define _CLR_OFFSET    0x04
> +#define _SET_OFFSET    0x08
> +#define _INV_OFFSET    0x0c
> +
> +static inline void __iomem *pic32_get_syscfg_base(void)
> +{
> +       return (void __iomem *)CKSEG1ADDR(PIC32_CFG_BASE);
> +}
> +
> +#endif /* __PIC32_REGS_H__ */
> --
> 1.8.3.1
>



-- 
- Daniel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 03/14] drivers: clk: Add clock driver for Microchip PIC32 Microcontroller.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 03/14] drivers: clk: Add clock driver for Microchip PIC32 Microcontroller Purna Chandra Mandal
@ 2016-01-13 13:38   ` Daniel Schwierzeck
  2016-01-14  5:34     ` Purna Chandra Mandal
  2016-01-13 14:55   ` Tom Rini
  1 sibling, 1 reply; 62+ messages in thread
From: Daniel Schwierzeck @ 2016-01-13 13:38 UTC (permalink / raw)
  To: u-boot

Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra Mandal:
> PIC32 clock module consists of multiple oscillators, PLLs,
> mutiplexers
> and dividers capable of supplying clock to various controllers
> on or off-chip.
> 
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

nits below

> 
> ---
> 
> Changes in v3:
> - rename clk-pic32.c to clk_pic32.c
> - update clock binding documentation
> - replace pic32_ioremap() with ioremap()
> - separate MPLL initialization constants
> 
> Changes in v2:
> - add mpll get clock rate
> 
>  .../clock/microchip,pic32-clock.txt                |  33 ++
>  drivers/clk/Makefile                               |   1 +
>  drivers/clk/clk_pic32.c                            | 433
> +++++++++++++++++++++
>  include/dt-bindings/clock/microchip,clock.h        |  29 ++
>  4 files changed, 496 insertions(+)
>  create mode 100644 doc/device-tree-bindings/clock/microchip,pic32
> -clock.txt
>  create mode 100644 drivers/clk/clk_pic32.c
>  create mode 100644 include/dt-bindings/clock/microchip,clock.h
> 
> diff --git a/doc/device-tree-bindings/clock/microchip,pic32-clock.txt
> b/doc/device-tree-bindings/clock/microchip,pic32-clock.txt
> new file mode 100644
> index 0000000..02e5ce4
> --- /dev/null
> +++ b/doc/device-tree-bindings/clock/microchip,pic32-clock.txt
> @@ -0,0 +1,33 @@
> +* Microchip PIC32 Clock and Oscillator
> +
> +Microchip PIC32 clock tree consists of few oscillators, PLLs,
> +multiplexers and few divider modules capable of supplying clocks
> +to various controllers within SoC and also to off-chip.
> +
> +PIC32 clock controller output is defined by indices as defined
> +in [0]
> +
> +[0] include/dt-bindings/clock/microchip,clock.h
> +
> +Required Properties:
> +- compatible: should be "microchip,pic32mzda_clk"
> +- reg: physical base address of the controller and length of memory
> mapped
> +       region.
> +- #clock-cells: should be 1.
> +
> +Example: Clock controller node:
> +
> +	clock: clk at 1f801200 {
> +		compatible = "microchip,pic32mzda_clk";
> +		reg = <0x1f801200 0x1000>;
> +	};
> +
> +Example: UART controller node that consumes the clock generated by
> the clock
> +controller:
> +
> +	uart1: serial at 1f822000 {
> +		compatible = "microchip,pic32mzda-uart";
> +		reg = <0xbf822000 0x50>;
> +		interrupts = <112 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&clock PB2CLK>;
> +	};
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 4a6a4a8..adda769 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -9,3 +9,4 @@ obj-$(CONFIG_CLK) += clk-uclass.o
>  obj-$(CONFIG_ROCKCHIP_RK3036) += clk_rk3036.o
>  obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o
>  obj-$(CONFIG_SANDBOX) += clk_sandbox.o
> +obj-$(CONFIG_MACH_PIC32) += clk_pic32.o
> diff --git a/drivers/clk/clk_pic32.c b/drivers/clk/clk_pic32.c
> new file mode 100644
> index 0000000..bb0a1cf
> --- /dev/null
> +++ b/drivers/clk/clk_pic32.c
> @@ -0,0 +1,433 @@
> +/*
> + * Copyright (C) 2015 Purna Chandra Mandal <
> purna.mandal at microchip.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + *
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <div64.h>
> +#include <wait_bit.h>
> +#include <dm/lists.h>
> +#include <asm/io.h>
> +#include <mach/pic32.h>
> +#include <dt-bindings/clock/microchip,clock.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* Primary oscillator */
> +#define SYS_POSC_CLK_HZ	24000000
> +
> +/* FRC clk rate */
> +#define SYS_FRC_CLK_HZ	8000000
> +
> +/* Clock Registers */
> +#define OSCCON		0x0000
> +#define OSCTUNE		0x0010
> +#define SPLLCON		0x0020
> +#define REFO1CON	0x0080
> +#define REFO1TRIM	0x0090
> +#define PB1DIV		0x0140
> +
> +/* SPLL */
> +#define ICLK_MASK	0x00000080
> +#define PLLIDIV_MASK	0x00000007
> +#define PLLODIV_MASK	0x00000007
> +#define CUROSC_MASK	0x00000007
> +#define PLLMUL_MASK	0x0000007F
> +#define FRCDIV_MASK	0x00000007
> +
> +/* PBCLK */
> +#define PBDIV_MASK	0x00000007
> +
> +/* SYSCLK MUX */
> +#define SCLK_SRC_FRC1	0
> +#define SCLK_SRC_SPLL	1
> +#define SCLK_SRC_POSC	2
> +#define SCLK_SRC_FRC2	7
> +
> +/* Reference Oscillator Control Reg fields */
> +#define REFO_SEL_MASK	0x0f
> +#define REFO_SEL_SHIFT	0
> +#define REFO_ACTIVE	BIT(8)
> +#define REFO_DIVSW_EN	BIT(9)
> +#define REFO_OE		BIT(12)
> +#define REFO_ON		BIT(15)
> +#define REFO_DIV_SHIFT	16
> +#define REFO_DIV_MASK	0x7fff
> +
> +/* Reference Oscillator Trim Register Fields */
> +#define REFO_TRIM_REG	0x10
> +#define REFO_TRIM_MASK	0x1ff
> +#define REFO_TRIM_SHIFT	23
> +#define REFO_TRIM_MAX	511
> +
> +#define ROCLK_SRC_SCLK		0x0
> +#define ROCLK_SRC_SPLL		0x7
> +#define ROCLK_SRC_ROCLKI	0x8
> +
> +/* Memory PLL */
> +#define MPLL_IDIV		0x3f
> +#define MPLL_MULT		0xff
> +#define MPLL_ODIV1		0x7
> +#define MPLL_ODIV2		0x7
> +#define MPLL_VREG_RDY		BIT(23)
> +#define MPLL_RDY		BIT(31)
> +#define MPLL_IDIV_SHIFT		0
> +#define MPLL_MULT_SHIFT		8
> +#define MPLL_ODIV1_SHIFT	24
> +#define MPLL_ODIV2_SHIFT	27
> +#define MPLL_IDIV_INIT		0x03
> +#define MPLL_MULT_INIT		0x32
> +#define MPLL_ODIV1_INIT		0x02
> +#define MPLL_ODIV2_INIT		0x01
> +
> +struct pic32_clk_priv {
> +	void __iomem *iobase;
> +	void __iomem *syscfg_base;
> +};
> +
> +static ulong pic32_get_pll_rate(struct pic32_clk_priv *priv)
> +{
> +	u32 iclk, idiv, odiv, mult;
> +	ulong plliclk, v;
> +
> +	v = readl(priv->iobase + SPLLCON);
> +	iclk = (v & ICLK_MASK);
> +	idiv = ((v >> 8) & PLLIDIV_MASK) + 1;
> +	odiv = ((v >> 24) & PLLODIV_MASK);
> +	mult = ((v >> 16) & PLLMUL_MASK) + 1;
> +
> +	plliclk = iclk ? SYS_FRC_CLK_HZ : SYS_POSC_CLK_HZ;
> +
> +	if (odiv < 2)
> +		odiv = 2;
> +	else if (odiv < 5)
> +		odiv = (1 << odiv);
> +	else
> +		odiv = 32;
> +
> +	return ((plliclk / idiv) * mult) / odiv;
> +}
> +
> +static ulong pic32_get_sysclk(struct pic32_clk_priv *priv)
> +{
> +	ulong v;
> +	ulong hz;
> +	ulong div, frcdiv;
> +	ulong curr_osc;
> +
> +	/* get clk source */
> +	v = readl(priv->iobase + OSCCON);
> +	curr_osc = (v >> 12) & CUROSC_MASK;
> +	switch (curr_osc) {
> +	case SCLK_SRC_FRC1:
> +	case SCLK_SRC_FRC2:
> +		frcdiv = ((v >> 24) & FRCDIV_MASK);
> +		div = ((1 << frcdiv) + 1) + (128 * (frcdiv == 7));
> +		hz = SYS_FRC_CLK_HZ / div;
> +		break;
> +
> +	case SCLK_SRC_SPLL:
> +		hz = pic32_get_pll_rate(priv);
> +		break;
> +
> +	case SCLK_SRC_POSC:
> +		hz = SYS_POSC_CLK_HZ;
> +		break;
> +
> +	default:
> +		hz = 0;
> +		printf("clk: unknown sclk_src.\n");
> +		break;
> +	}
> +
> +	return hz;
> +}
> +
> +static ulong pic32_get_pbclk(struct pic32_clk_priv *priv, int
> periph)
> +{
> +	void __iomem *reg;
> +	ulong div, clk_freq;
> +
> +	WARN_ON((periph < PB1CLK) || (periph > PB7CLK));
> +
> +	clk_freq = pic32_get_sysclk(priv);
> +
> +	reg = priv->iobase + PB1DIV + (periph - PB1CLK) * 0x10;
> +	div = (readl(reg) & PBDIV_MASK) + 1;
> +
> +	return clk_freq / div;
> +}
> +
> +static ulong pic32_get_cpuclk(struct pic32_clk_priv *priv)
> +{
> +	return pic32_get_pbclk(priv, PB7CLK);
> +}
> +
> +static ulong pic32_set_refclk(struct pic32_clk_priv *priv, int
> periph,
> +			      int parent_rate, int rate, int
> parent_id)
> +{
> +	void __iomem *reg;
> +	u32 div, trim, v;
> +	u64 frac;
> +
> +	WARN_ON((periph < REF1CLK) || (periph > REF5CLK));
> +
> +	/* calculate dividers,
> +	 *   rate = parent_rate / [2 * (div + (trim / 512))]
> +	 */
> +	if (parent_rate <= rate) {
> +		div = 0;
> +		trim = 0;
> +	} else {
> +		div = parent_rate / (rate << 1);
> +		frac = parent_rate;
> +		frac <<= 8;
> +		do_div(frac, rate);
> +		frac -= (u64)(div << 9);
> +		trim = (frac >= REFO_TRIM_MAX) ? REFO_TRIM_MAX :
> (u32)frac;
> +	}
> +
> +	reg = priv->iobase + REFO1CON + (periph - REF1CLK) * 0x20;
> +
> +	/* disable clk */
> +	writel(REFO_ON | REFO_OE, reg + _CLR_OFFSET);
> +
> +	/* wait till previous src change is active */
> +	wait_for_bit(__func__, reg, REFO_DIVSW_EN | REFO_ACTIVE,
> +		     false, CONFIG_SYS_HZ, false);
> +
> +	/* parent_id */
> +	v = readl(reg);
> +	v &= ~(REFO_SEL_MASK << REFO_SEL_SHIFT);
> +	v |= (parent_id << REFO_SEL_SHIFT);
> +
> +	/* apply rodiv */
> +	v &= ~(REFO_DIV_MASK << REFO_DIV_SHIFT);
> +	v |= (div << REFO_DIV_SHIFT);
> +	writel(v, reg);
> +
> +	/* apply trim */
> +	v = readl(reg + REFO_TRIM_REG);
> +	v &= ~(REFO_TRIM_MASK << REFO_TRIM_SHIFT);
> +	v |= (trim << REFO_TRIM_SHIFT);
> +	writel(v, reg + REFO_TRIM_REG);
> +
> +	/* enable clk */
> +	writel(REFO_ON | REFO_OE, reg + _SET_OFFSET);
> +
> +	/* switch divider */
> +	writel(REFO_DIVSW_EN, reg + _SET_OFFSET);
> +
> +	/* wait for divider switching to complete */
> +	return wait_for_bit(__func__, reg, REFO_DIVSW_EN, false,
> +			    CONFIG_SYS_HZ, false);
> +}
> +
> +static ulong pic32_get_refclk(struct pic32_clk_priv *priv, int
> periph)
> +{
> +	u32 rodiv, rotrim, rosel, v, parent_rate;
> +	void __iomem *reg;
> +	u64 rate64;
> +
> +	WARN_ON((periph < REF1CLK) || (periph > REF5CLK));
> +
> +	reg = priv->iobase + REFO1CON + (periph - REF1CLK) * 0x20;
> +	v = readl(reg);
> +	/* get rosel */
> +	rosel = (v >> REFO_SEL_SHIFT) & REFO_SEL_MASK;
> +	/* get div */
> +	rodiv = (v >> REFO_DIV_SHIFT) & REFO_DIV_MASK;
> +
> +	/* get trim */
> +	v = readl(reg + REFO_TRIM_REG);
> +	rotrim = (v >> REFO_TRIM_SHIFT) & REFO_TRIM_MASK;
> +
> +	if (!rodiv)
> +		return 0;
> +
> +	/* get parent rate */
> +	switch (rosel) {
> +	case ROCLK_SRC_SCLK:
> +		parent_rate = pic32_get_cpuclk(priv);
> +		break;
> +	case ROCLK_SRC_SPLL:
> +		parent_rate = pic32_get_pll_rate(priv);
> +		break;
> +	default:
> +		parent_rate = 0;
> +		break;
> +	}
> +
> +	/* Calculation
> +	 * rate = parent_rate / [2 * (div + (trim / 512))]
> +	 */
> +	if (rotrim) {
> +		rodiv <<= 9;
> +		rodiv += rotrim;
> +		rate64 = parent_rate;
> +		rate64 <<= 8;
> +		do_div(rate64, rodiv);
> +		v = (u32)rate64;
> +	} else {
> +		v = parent_rate / (rodiv << 1);
> +	}
> +	return v;
> +}
> +
> +static ulong pic32_get_mpll_rate(struct pic32_clk_priv *priv)
> +{
> +	u32 v, idiv, mul;
> +	u32 odiv1, odiv2;
> +	u64 rate;
> +
> +	v = readl(priv->syscfg_base + CFGMPLL);
> +	idiv = v & MPLL_IDIV;
> +	mul = (v >> MPLL_MULT_SHIFT) & MPLL_MULT;
> +	odiv1 = (v >> MPLL_ODIV1_SHIFT) & MPLL_ODIV1;
> +	odiv2 = (v >> MPLL_ODIV2_SHIFT) & MPLL_ODIV2;
> +
> +	rate = (SYS_POSC_CLK_HZ / idiv) * mul;
> +	do_div(rate, odiv1);
> +	do_div(rate, odiv2);
> +
> +	return (ulong)rate;
> +}
> +
> +static int pic32_mpll_init(struct pic32_clk_priv *priv)
> +{
> +	u32 v, mask;
> +
> +	/* initialize */
> +	v = (MPLL_IDIV_INIT << MPLL_IDIV_SHIFT) |
> +	    (MPLL_MULT_INIT << MPLL_MULT_SHIFT) |
> +	    (MPLL_ODIV1_INIT << MPLL_ODIV1_SHIFT) |
> +	    (MPLL_ODIV2_INIT << MPLL_ODIV2_SHIFT);
> +
> +	writel(v, priv->syscfg_base + CFGMPLL);
> +
> +	/* Wait for ready */
> +	mask = MPLL_RDY | MPLL_VREG_RDY;
> +	return wait_for_bit(__func__, priv->syscfg_base + CFGMPLL,
> mask,
> +			    true, get_tbclk(), false);
> +}
> +
> +static void pic32_clk_init(struct udevice *dev)
> +{
> +	const void *blob = gd->fdt_blob;
> +	struct pic32_clk_priv *priv;
> +	ulong rate, pll_hz;
> +	char propname[50];
> +	int i;
> +
> +	priv = dev_get_priv(dev);
> +	pll_hz = pic32_get_pll_rate(priv);
> +
> +	/* Initialize REFOs as not initialized and enabled on reset.
> */
> +	for (i = REF1CLK; i <= REF5CLK; i++) {
> +		snprintf(propname, sizeof(propname),
> +			 "microchip,refo%d-frequency", i - REF1CLK +
> 1);
> +		rate = fdtdec_get_int(blob, dev->of_offset,
> propname, 0);
> +		if (rate)
> +			pic32_set_refclk(priv, i, pll_hz, rate,
> ROCLK_SRC_SPLL);
> +	}
> +
> +	/* Memory PLL */
> +	pic32_mpll_init(priv);
> +}
> +
> +static ulong pic32_clk_get_rate(struct udevice *dev)
> +{
> +	struct pic32_clk_priv *priv = dev_get_priv(dev);
> +
> +	return pic32_get_cpuclk(priv);
> +}
> +
> +static ulong pic32_get_periph_rate(struct udevice *dev, int periph)
> +{
> +	struct pic32_clk_priv *priv = dev_get_priv(dev);
> +	ulong rate;
> +
> +	switch (periph) {
> +	case PB1CLK ... PB7CLK:
> +		rate = pic32_get_pbclk(priv, periph);
> +		break;
> +	case REF1CLK ... REF5CLK:
> +		rate = pic32_get_refclk(priv, periph);
> +		break;
> +	case PLLCLK:
> +		rate = pic32_get_pll_rate(priv);
> +		break;
> +	case MPLL:
> +		rate = pic32_get_mpll_rate(priv);
> +		break;
> +	default:
> +		rate = 0;
> +		break;
> +	}
> +
> +	return rate;
> +}
> +
> +static ulong pic32_set_periph_rate(struct udevice *dev, int periph,
> ulong rate)
> +{
> +	struct pic32_clk_priv *priv = dev_get_priv(dev);
> +	ulong pll_hz;
> +
> +	switch (periph) {
> +	case REF1CLK ... REF5CLK:
> +		pll_hz = pic32_get_pll_rate(priv);
> +		pic32_set_refclk(priv, periph, pll_hz, rate,
> ROCLK_SRC_SPLL);
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return rate;
> +}
> +
> +static struct clk_ops pic32_pic32_clk_ops = {
> +	.get_rate = pic32_clk_get_rate,
> +	.set_periph_rate = pic32_set_periph_rate,
> +	.get_periph_rate = pic32_get_periph_rate,
> +};
> +
> +static int pic32_clk_probe(struct udevice *dev)
> +{
> +	struct pic32_clk_priv *priv = dev_get_priv(dev);
> +	fdt_addr_t addr;
> +	fdt_size_t size;
> +
> +	addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset,
> "reg", &size);
> +	if (addr == FDT_ADDR_T_NONE)
> +		return -EINVAL;
> +
> +	priv->iobase = ioremap(addr, size);
> +	if (!priv->iobase)
> +		return -EINVAL;

you can drop this check. ioremap() always returns a mapped address

> +
> +	priv->syscfg_base = pic32_get_syscfg_base();
> +
> +	/* initialize clocks */
> +	pic32_clk_init(dev);
> +
> +	return 0;
> +}
> +
> +static const struct udevice_id pic32_clk_ids[] = {
> +	{ .compatible = "microchip,pic32mzda_clk"},
> +	{}
> +};
> +
> +U_BOOT_DRIVER(pic32_clk) = {
> +	.name		= "pic32_clk",
> +	.id		= UCLASS_CLK,
> +	.of_match	= pic32_clk_ids,
> +	.flags		= DM_FLAG_PRE_RELOC,
> +	.ops		= &pic32_pic32_clk_ops,
> +	.probe		= pic32_clk_probe,
> +	.priv_auto_alloc_size = sizeof(struct pic32_clk_priv),
> +};
> diff --git a/include/dt-bindings/clock/microchip,clock.h b/include/dt
> -bindings/clock/microchip,clock.h
> new file mode 100644
> index 0000000..93c222d
> --- /dev/null
> +++ b/include/dt-bindings/clock/microchip,clock.h
> @@ -0,0 +1,29 @@
> +/*
> + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + *
> + */
> +
> +#ifndef __CLK_MICROCHIP_PIC32
> +#define __CLK_MICROCHIP_PIC32
> +
> +/* clock output indices */
> +#define BASECLK	0
> +#define PLLCLK	1
> +#define MPLL	2
> +#define SYSCLK	3
> +#define PB1CLK	4
> +#define PB2CLK	5
> +#define PB3CLK	6
> +#define PB4CLK	7
> +#define PB5CLK	8
> +#define PB6CLK	9
> +#define PB7CLK	10
> +#define REF1CLK	11
> +#define REF2CLK	12
> +#define REF3CLK	13
> +#define REF4CLK	14
> +#define REF5CLK	15
> +
> +#endif	/* __CLK_MICROCHIP_PIC32 */
-- 
- Daniel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 04/14] drivers: pinctrl: Add pinctrl driver for Microchip PIC32.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 04/14] drivers: pinctrl: Add pinctrl driver for Microchip PIC32 Purna Chandra Mandal
@ 2016-01-13 13:42   ` Daniel Schwierzeck
  2016-01-13 14:55   ` Tom Rini
  2016-01-13 20:10   ` Simon Glass
  2 siblings, 0 replies; 62+ messages in thread
From: Daniel Schwierzeck @ 2016-01-13 13:42 UTC (permalink / raw)
  To: u-boot

Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra Mandal:
> In PIC32 pin-controller is a combined gpio-controller, pin-mux and
> pin-config module. Remappable peripherals are assigned pins through
> per-pin based muxing logic. And pin configuration are performed on
> specific port registers which are shared along with gpio controller.
> Note, non-remappable peripherals have default pins assigned thus
> require
> no muxing.
> 
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> 

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

> 
> ---
> 
> Changes in v3:
> - read register base from device-tree
> - add/update comments to explain how pinctrl'r works.
> - replace pic32_ioremap() with ioremap().
> 
> Changes in v2:
> - add pinconf routine for configuring pin property
> 
>  drivers/pinctrl/Kconfig         |   9 +
>  drivers/pinctrl/Makefile        |   1 +
>  drivers/pinctrl/pinctrl_pic32.c | 363
> ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 373 insertions(+)
>  create mode 100644 drivers/pinctrl/pinctrl_pic32.c
> 
> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
> index 57e6142..292c4e2 100644
> --- a/drivers/pinctrl/Kconfig
> +++ b/drivers/pinctrl/Kconfig
> @@ -131,6 +131,15 @@ config PINCTRL_SANDBOX
>  	  actually does nothing but print debug messages when
> pinctrl
>  	  operations are invoked.
>  
> +config PIC32_PINCTRL
> +	bool "Microchip PIC32 pin-control and pin-mux driver"
> +	depends on DM && MACH_PIC32
> +	help
> +	  Supports individual pin selection and configuration for
> each remappable
> +	  peripheral available on Microchip PIC32 SoCs. This driver
> is controlled
> +	  by a device tree node which contains both GPIO defintion
> and pin control
> +	  functions.
> +
>  endif
>  
>  source "drivers/pinctrl/uniphier/Kconfig"
> diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
> index 70d25dc..b4f4650 100644
> --- a/drivers/pinctrl/Makefile
> +++ b/drivers/pinctrl/Makefile
> @@ -9,3 +9,4 @@ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
>  obj-$(CONFIG_PINCTRL_SANDBOX)	+= pinctrl-sandbox.o
>  
>  obj-$(CONFIG_ARCH_UNIPHIER)	+= uniphier/
> +obj-$(CONFIG_PIC32_PINCTRL)	+= pinctrl_pic32.o
> diff --git a/drivers/pinctrl/pinctrl_pic32.c
> b/drivers/pinctrl/pinctrl_pic32.c
> new file mode 100644
> index 0000000..5cf97ec
> --- /dev/null
> +++ b/drivers/pinctrl/pinctrl_pic32.c
> @@ -0,0 +1,363 @@
> +/*
> + * Pinctrl driver for Microchip PIC32 SoCs
> + * Copyright (c) 2015 Microchip Technology Inc.
> + * Written by Purna Chandra Mandal <purna.mandal@microchip.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <asm/io.h>
> +#include <dm/pinctrl.h>
> +#include <dm/root.h>
> +#include <mach/pic32.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* PIC32 has 10 peripheral ports with 16 pins each.
> + * Ports are marked PORTA-PORTK or PORT0-PORT9.
> + */
> +enum {
> +	PIC32_PORT_A = 0,
> +	PIC32_PORT_B = 1,
> +	PIC32_PORT_C = 2,
> +	PIC32_PORT_D = 3,
> +	PIC32_PORT_E = 4,
> +	PIC32_PORT_F = 5,
> +	PIC32_PORT_G = 6,
> +	PIC32_PORT_H = 7,
> +	PIC32_PORT_J = 8, /* no PORT_I */
> +	PIC32_PORT_K = 9,
> +	PIC32_PINS_PER_PORT = 16,
> +};
> +
> +#define PIN_CONFIG_PIC32_DIGITAL	(PIN_CONFIG_END + 1)
> +#define PIN_CONFIG_PIC32_ANALOG		(PIN_CONFIG_END + 2)
> +
> +/* pin configuration descriptor */
> +struct pic32_pin_config {
> +	u16 port;	/* port number */
> +	u16 pin;	/* pin number in the port */
> +	u32 config;	/* one of PIN_CONFIG_* */
> +};
> +#define PIN_CONFIG(_prt, _pin, _cfg) \
> +	{.port = (_prt), .pin = (_pin), .config = (_cfg), }
> +
> +/* In PIC32 muxing is performed at pin-level through two
> + * different set of registers - one set for input functions,
> + * and other for output functions.
> + * Pin configuration is handled through port register.
> + */
> +/* Port control registers */
> +struct pic32_reg_port {
> +	struct pic32_reg_atomic ansel;
> +	struct pic32_reg_atomic tris;
> +	struct pic32_reg_atomic port;
> +	struct pic32_reg_atomic lat;
> +	struct pic32_reg_atomic odc;
> +	struct pic32_reg_atomic cnpu;
> +	struct pic32_reg_atomic cnpd;
> +	struct pic32_reg_atomic cncon;
> +	struct pic32_reg_atomic unused[8];
> +};
> +
> +/* Input function mux registers */
> +struct pic32_reg_in_mux {
> +	u32 unused0;
> +	u32 int1[4];
> +	u32 unused1;
> +	u32 t2ck[8];
> +	u32 ic1[9];
> +	u32 unused2;
> +	u32 ocfar;
> +	u32 unused3;
> +	u32 u1rx;
> +	u32 u1cts;
> +	u32 u2rx;
> +	u32 u2cts;
> +	u32 u3rx;
> +	u32 u3cts;
> +	u32 u4rx;
> +	u32 u4cts;
> +	u32 u5rx;
> +	u32 u5cts;
> +	u32 u6rx;
> +	u32 u6cts;
> +	u32 unused4;
> +	u32 sdi1;
> +	u32 ss1;
> +	u32 unused5;
> +	u32 sdi2;
> +	u32 ss2;
> +	u32 unused6;
> +	u32 sdi3;
> +	u32 ss3;
> +	u32 unused7;
> +	u32 sdi4;
> +	u32 ss4;
> +	u32 unused8;
> +	u32 sdi5;
> +	u32 ss5;
> +	u32 unused9;
> +	u32 sdi6;
> +	u32 ss6;
> +	u32 c1rx;
> +	u32 c2rx;
> +	u32 refclki1;
> +	u32 refclki2;
> +	u32 refclki3;
> +	u32 refclki4;
> +};
> +
> +/* output mux register offset */
> +#define PPS_OUT(__port, __pin) \
> +	(((__port) * PIC32_PINS_PER_PORT + (__pin)) << 2)
> +
> +
> +struct pic32_pinctrl_priv {
> +	struct pic32_reg_in_mux *mux_in; /* mux input function */
> +	struct pic32_reg_port *pinconf; /* pin configuration*/
> +	void __iomem *mux_out;	/* mux output function */
> +};
> +
> +enum {
> +	PERIPH_ID_UART1,
> +	PERIPH_ID_UART2,
> +	PERIPH_ID_ETH,
> +	PERIPH_ID_USB,
> +	PERIPH_ID_SDHCI,
> +	PERIPH_ID_I2C1,
> +	PERIPH_ID_I2C2,
> +	PERIPH_ID_SPI1,
> +	PERIPH_ID_SPI2,
> +	PERIPH_ID_SQI,
> +};
> +
> +static int pic32_pinconfig_one(struct pic32_pinctrl_priv *priv,
> +			       u32 port_nr, u32 pin, u32 param)
> +{
> +	struct pic32_reg_port *port;
> +
> +	port = &priv->pinconf[port_nr];
> +	switch (param) {
> +	case PIN_CONFIG_PIC32_DIGITAL:
> +		writel(BIT(pin), &port->ansel.clr);
> +		break;
> +	case PIN_CONFIG_PIC32_ANALOG:
> +		writel(BIT(pin), &port->ansel.set);
> +		break;
> +	case PIN_CONFIG_INPUT_ENABLE:
> +		writel(BIT(pin), &port->tris.set);
> +		break;
> +	case PIN_CONFIG_OUTPUT:
> +		writel(BIT(pin), &port->tris.clr);
> +		break;
> +	case PIN_CONFIG_BIAS_PULL_UP:
> +		writel(BIT(pin), &port->cnpu.set);
> +		break;
> +	case PIN_CONFIG_BIAS_PULL_DOWN:
> +		writel(BIT(pin), &port->cnpd.set);
> +		break;
> +	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
> +		writel(BIT(pin), &port->odc.set);
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static int pic32_pinconfig_set(struct pic32_pinctrl_priv *priv,
> +			       const struct pic32_pin_config *list,
> int count)
> +{
> +	int i;
> +
> +	for (i = 0 ; i < count; i++)
> +		pic32_pinconfig_one(priv, list[i].port,
> +				    list[i].pin, list[i].config);
> +
> +	return 0;
> +}
> +
> +static void pic32_eth_pin_config(struct udevice *dev)
> +{
> +	struct pic32_pinctrl_priv *priv = dev_get_priv(dev);
> +	const struct pic32_pin_config configs[] = {
> +		/* EMDC - D11 */
> +		PIN_CONFIG(PIC32_PORT_D, 11,
> PIN_CONFIG_PIC32_DIGITAL),
> +		PIN_CONFIG(PIC32_PORT_D, 11, PIN_CONFIG_OUTPUT),
> +		/* ETXEN */
> +		PIN_CONFIG(PIC32_PORT_D, 6,
> PIN_CONFIG_PIC32_DIGITAL),
> +		PIN_CONFIG(PIC32_PORT_D, 6, PIN_CONFIG_OUTPUT),
> +		/* ECRSDV */
> +		PIN_CONFIG(PIC32_PORT_H, 13,
> PIN_CONFIG_PIC32_DIGITAL),
> +		PIN_CONFIG(PIC32_PORT_H, 13,
> PIN_CONFIG_INPUT_ENABLE),
> +		/* ERXD0 */
> +		PIN_CONFIG(PIC32_PORT_H, 8,
> PIN_CONFIG_PIC32_DIGITAL),
> +		PIN_CONFIG(PIC32_PORT_H, 8,
> PIN_CONFIG_INPUT_ENABLE),
> +		PIN_CONFIG(PIC32_PORT_H, 8,
> PIN_CONFIG_BIAS_PULL_DOWN),
> +		/* ERXD1 */
> +		PIN_CONFIG(PIC32_PORT_H, 5,
> PIN_CONFIG_PIC32_DIGITAL),
> +		PIN_CONFIG(PIC32_PORT_H, 5,
> PIN_CONFIG_INPUT_ENABLE),
> +		PIN_CONFIG(PIC32_PORT_H, 5,
> PIN_CONFIG_BIAS_PULL_DOWN),
> +		/* EREFCLK */
> +		PIN_CONFIG(PIC32_PORT_J, 11,
> PIN_CONFIG_PIC32_DIGITAL),
> +		PIN_CONFIG(PIC32_PORT_J, 11,
> PIN_CONFIG_INPUT_ENABLE),
> +		/* ETXD1 */
> +		PIN_CONFIG(PIC32_PORT_J, 9,
> PIN_CONFIG_PIC32_DIGITAL),
> +		PIN_CONFIG(PIC32_PORT_J, 9, PIN_CONFIG_OUTPUT),
> +		/* ETXD0 */
> +		PIN_CONFIG(PIC32_PORT_J, 8,
> PIN_CONFIG_PIC32_DIGITAL),
> +		PIN_CONFIG(PIC32_PORT_J, 8, PIN_CONFIG_OUTPUT),
> +		/* EMDIO */
> +		PIN_CONFIG(PIC32_PORT_J, 1,
> PIN_CONFIG_PIC32_DIGITAL),
> +		PIN_CONFIG(PIC32_PORT_J, 1,
> PIN_CONFIG_INPUT_ENABLE),
> +		/* ERXERR */
> +		PIN_CONFIG(PIC32_PORT_F, 3,
> PIN_CONFIG_PIC32_DIGITAL),
> +		PIN_CONFIG(PIC32_PORT_F, 3,
> PIN_CONFIG_INPUT_ENABLE),
> +	};
> +
> +	pic32_pinconfig_set(priv, configs, ARRAY_SIZE(configs));
> +}
> +
> +static int pic32_pinctrl_request(struct udevice *dev, int func, int
> flags)
> +{
> +	struct pic32_pinctrl_priv *priv = dev_get_priv(dev);
> +
> +	switch (func) {
> +	case PERIPH_ID_UART2:
> +		/* PPS for U2 RX/TX */
> +		writel(0x02, priv->mux_out + PPS_OUT(PIC32_PORT_G,
> 9));
> +		writel(0x05, &priv->mux_in->u2rx); /* B0 */
> +		/* set digital mode */
> +		pic32_pinconfig_one(priv, PIC32_PORT_G, 9,
> +				    PIN_CONFIG_PIC32_DIGITAL);
> +		pic32_pinconfig_one(priv, PIC32_PORT_B, 0,
> +				    PIN_CONFIG_PIC32_DIGITAL);
> +		break;
> +	case PERIPH_ID_ETH:
> +		pic32_eth_pin_config(dev);
> +		break;
> +	default:
> +		debug("%s: unknown-unhandled case\n", __func__);
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static int pic32_pinctrl_get_periph_id(struct udevice *dev,
> +				       struct udevice *periph)
> +{
> +	int ret;
> +	u32 cell[2];
> +
> +	ret = fdtdec_get_int_array(gd->fdt_blob, periph->of_offset,
> +				   "interrupts", cell,
> ARRAY_SIZE(cell));
> +	if (ret < 0)
> +		return -EINVAL;
> +
> +	/* interrupt number */
> +	switch (cell[0]) {
> +	case 112 ... 114:
> +		return PERIPH_ID_UART1;
> +	case 145 ... 147:
> +		return PERIPH_ID_UART2;
> +	case 109 ... 111:
> +		return PERIPH_ID_SPI1;
> +	case 142 ... 144:
> +		return PERIPH_ID_SPI2;
> +	case 115 ... 117:
> +		return PERIPH_ID_I2C1;
> +	case 148 ... 150:
> +		return PERIPH_ID_I2C2;
> +	case 132 ... 133:
> +		return PERIPH_ID_USB;
> +	case 169:
> +		return PERIPH_ID_SQI;
> +	case 191:
> +		return PERIPH_ID_SDHCI;
> +	case 153:
> +		return PERIPH_ID_ETH;
> +	default:
> +		break;
> +	}
> +
> +	return -ENOENT;
> +}
> +
> +static int pic32_pinctrl_set_state_simple(struct udevice *dev,
> +					  struct udevice *periph)
> +{
> +	int func;
> +
> +	debug("%s: periph %s\n", __func__, periph->name);
> +	func = pic32_pinctrl_get_periph_id(dev, periph);
> +	if (func < 0)
> +		return func;
> +	return pic32_pinctrl_request(dev, func, 0);
> +}
> +
> +static struct pinctrl_ops pic32_pinctrl_ops = {
> +	.set_state_simple	= pic32_pinctrl_set_state_simple,
> +	.request		= pic32_pinctrl_request,
> +	.get_periph_id		= pic32_pinctrl_get_periph_id,
> +};
> +
> +static int pic32_pinctrl_probe(struct udevice *dev)
> +{
> +	struct pic32_pinctrl_priv *priv = dev_get_priv(dev);
> +	struct fdt_resource res;
> +	void *fdt = (void *)gd->fdt_blob;
> +	int node = dev->of_offset;
> +	int ret;
> +
> +	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
> +				     "ppsin", &res);
> +	if (ret < 0) {
> +		printf("pinctrl: resource \"ppsin\" not found\n");
> +		return ret;
> +	}
> +	priv->mux_in = ioremap(res.start, fdt_resource_size(&res));
> +
> +	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
> +				     "ppsout", &res);
> +	if (ret < 0) {
> +		printf("pinctrl: resource \"ppsout\" not found\n");
> +		return ret;
> +	}
> +	priv->mux_out = ioremap(res.start, fdt_resource_size(&res));
> +
> +	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
> +				     "port", &res);
> +	if (ret < 0) {
> +		printf("pinctrl: resource \"port\" not found\n");
> +		return ret;
> +	}
> +	priv->pinconf = ioremap(res.start, fdt_resource_size(&res));
> +
> +	return 0;
> +}
> +
> +static int pic32_pinctrl_bind(struct udevice *dev)
> +{
> +	/* scan child GPIO banks */
> +	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset,
> false);
> +}
> +
> +static const struct udevice_id pic32_pinctrl_ids[] = {
> +	{ .compatible = "microchip,pic32mzda-pinctrl" },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(pinctrl_pic32) = {
> +	.name		= "pinctrl_pic32",
> +	.id		= UCLASS_PINCTRL,
> +	.of_match	= pic32_pinctrl_ids,
> +	.ops		= &pic32_pinctrl_ops,
> +	.probe		= pic32_pinctrl_probe,
> +	.bind		= pic32_pinctrl_bind,
> +	.priv_auto_alloc_size = sizeof(struct pic32_pinctrl_priv),
> +};
-- 
- Daniel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 05/14] drivers: gpio: add driver for Microchip PIC32 GPIO controller.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 05/14] drivers: gpio: add driver for Microchip PIC32 GPIO controller Purna Chandra Mandal
@ 2016-01-13 13:46   ` Daniel Schwierzeck
  2016-01-13 14:08     ` Daniel Schwierzeck
  2016-01-13 14:55   ` Tom Rini
  2016-01-13 20:10   ` Simon Glass
  2 siblings, 1 reply; 62+ messages in thread
From: Daniel Schwierzeck @ 2016-01-13 13:46 UTC (permalink / raw)
  To: u-boot

Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra Mandal:
> In PIC32 GPIO controller is part of PIC32 pin controller.
> PIC32 has ten independently programmable ports and each with multiple
> pins.
> Each of these pins can be configured and used as GPIO, provided they
> are not in use for other peripherals.
> 
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

nits below

> 
> ---
> 
> Changes in v3:
> - add check on dev_get_addr()
> 
> Changes in v2: None
> 
>  drivers/gpio/Kconfig      |   7 ++
>  drivers/gpio/Makefile     |   2 +-
>  drivers/gpio/pic32_gpio.c | 175
> ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 183 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpio/pic32_gpio.c
> 
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index e60e9fd..13e9a6a 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -83,4 +83,11 @@ config VYBRID_GPIO
>  	help
>  	  Say yes here to support Vybrid vf610 GPIOs.
>  
> +config PIC32_GPIO
> +	bool "Microchip PIC32 GPIO driver"
> +	depends on DM_GPIO
> +	default y if MACH_PIC32
> +	help
> +	  Say yes here to support Microchip PIC32 GPIOs.
> +
>  endmenu
> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> index fb4fd25..845a6d4 100644
> --- a/drivers/gpio/Makefile
> +++ b/drivers/gpio/Makefile
> @@ -46,4 +46,4 @@ obj-$(CONFIG_STM32_GPIO)	+= stm32_gpio.o
>  obj-$(CONFIG_ZYNQ_GPIO)		+= zynq_gpio.o
>  obj-$(CONFIG_VYBRID_GPIO)	+= vybrid_gpio.o
>  obj-$(CONFIG_HIKEY_GPIO)	+= hi6220_gpio.o
> -
> +obj-$(CONFIG_PIC32_GPIO)	+= pic32_gpio.o
> diff --git a/drivers/gpio/pic32_gpio.c b/drivers/gpio/pic32_gpio.c
> new file mode 100644
> index 0000000..5b23af4
> --- /dev/null
> +++ b/drivers/gpio/pic32_gpio.c
> @@ -0,0 +1,175 @@
> +/*
> + * Copyright (c) 2015 Microchip Technology Inc
> + * Purna Chandra Mandal <purna.mandal@microchip.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <malloc.h>
> +#include <asm/io.h>
> +#include <asm/gpio.h>
> +#include <linux/compat.h>
> +#include <dt-bindings/gpio/gpio.h>
> +#include <mach/pic32.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* Peripheral Pin Control */
> +struct pic32_reg_port {
> +	struct pic32_reg_atomic ansel;
> +	struct pic32_reg_atomic tris;
> +	struct pic32_reg_atomic port;
> +	struct pic32_reg_atomic lat;
> +	struct pic32_reg_atomic open_drain;
> +	struct pic32_reg_atomic cnpu;
> +	struct pic32_reg_atomic cnpd;
> +	struct pic32_reg_atomic cncon;
> +};
> +
> +enum {
> +	MICROCHIP_GPIO_DIR_OUT,
> +	MICROCHIP_GPIO_DIR_IN,
> +	MICROCHIP_GPIOS_PER_BANK = 16,
> +};
> +
> +struct pic32_gpio_priv {
> +	struct pic32_reg_port *regs;
> +	char name[2];
> +};
> +
> +static int pic32_gpio_get_value(struct udevice *dev, unsigned
> offset)
> +{
> +	struct pic32_gpio_priv *priv = dev_get_priv(dev);
> +
> +	return !!(readl(&priv->regs->port.raw) & BIT(offset));
> +}
> +
> +static int pic32_gpio_set_value(struct udevice *dev, unsigned
> offset,
> +				int value)
> +{
> +	struct pic32_gpio_priv *priv = dev_get_priv(dev);
> +	int mask = BIT(offset);
> +
> +	if (value)
> +		writel(mask, &priv->regs->port.set);
> +	else
> +		writel(mask, &priv->regs->port.clr);
> +
> +	return 0;
> +}
> +
> +static int pic32_gpio_direction(struct udevice *dev, unsigned
> offset)
> +{
> +	struct pic32_gpio_priv *priv = dev_get_priv(dev);
> +
> +	if (readl(&priv->regs->ansel.raw) & BIT(offset))
> +		return -1;
> +
> +	if (readl(&priv->regs->tris.raw) & BIT(offset))
> +		return MICROCHIP_GPIO_DIR_IN;
> +	else
> +		return MICROCHIP_GPIO_DIR_OUT;
> +}
> +
> +static int pic32_gpio_direction_input(struct udevice *dev, unsigned
> offset)
> +{
> +	struct pic32_gpio_priv *priv = dev_get_priv(dev);
> +	int mask = BIT(offset);
> +
> +	writel(mask, &priv->regs->ansel.clr);
> +	writel(mask, &priv->regs->tris.set);
> +
> +	return 0;
> +}
> +
> +static int pic32_gpio_direction_output(struct udevice *dev,
> +				       unsigned offset, int value)
> +{
> +	struct pic32_gpio_priv *priv = dev_get_priv(dev);
> +	int mask = BIT(offset);
> +
> +	writel(mask, &priv->regs->ansel.clr);
> +	writel(mask, &priv->regs->tris.clr);
> +
> +	pic32_gpio_set_value(dev, offset, value);
> +	return 0;
> +}
> +
> +static int pic32_gpio_xlate(struct udevice *dev, struct gpio_desc
> *desc,
> +			    struct fdtdec_phandle_args *args)
> +{
> +	desc->offset = args->args[0];
> +	desc->flags = args->args[1] & GPIO_ACTIVE_LOW ?
> GPIOD_ACTIVE_LOW : 0;
> +
> +	return 0;
> +}
> +
> +static int pic32_gpio_get_function(struct udevice *dev, unsigned
> offset)
> +{
> +	int ret = GPIOF_UNUSED;
> +
> +	switch (pic32_gpio_direction(dev, offset)) {
> +	case MICROCHIP_GPIO_DIR_OUT:
> +		ret = GPIOF_OUTPUT;
> +		break;
> +	case MICROCHIP_GPIO_DIR_IN:
> +		ret = GPIOF_INPUT;
> +		break;
> +	default:
> +		ret = GPIOF_UNUSED;
> +		break;
> +	}
> +	return ret;
> +}
> +
> +static const struct dm_gpio_ops gpio_pic32_ops = {
> +	.direction_input	= pic32_gpio_direction_input,
> +	.direction_output	= pic32_gpio_direction_output,
> +	.get_value		= pic32_gpio_get_value,
> +	.set_value		= pic32_gpio_set_value,
> +	.get_function		= pic32_gpio_get_function,
> +	.xlate			= pic32_gpio_xlate,
> +};
> +
> +static int pic32_gpio_probe(struct udevice *dev)
> +{
> +	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
> +	struct pic32_gpio_priv *priv = dev_get_priv(dev);
> +	fdt_addr_t addr;
> +	fdt_size_t size;
> +	char *end;
> +	int bank;
> +
> +	addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset,
> "reg", &size);
> +	if (addr == FDT_ADDR_T_NONE)
> +		return -EINVAL;
> +
> +	priv->regs = ioremap(addr, size);
> +	if (!priv->regs)
> +		return -EINVAL;

you can drop this check. ioremap() always returns a mapped address.

> +
> +	uc_priv->gpio_count = MICROCHIP_GPIOS_PER_BANK;
> +	end = strrchr(dev->name, '@');
> +	bank = trailing_strtoln(dev->name, end);
> +	priv->name[0] = 'A' + bank;
> +	uc_priv->bank_name = priv->name;
> +
> +	return 0;
> +}
> +
> +static const struct udevice_id pic32_gpio_ids[] = {
> +	{ .compatible = "microchip,pic32mzda-gpio" },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(gpio_pic32) = {
> +	.name		= "gpio_pic32",
> +	.id		= UCLASS_GPIO,
> +	.of_match	= pic32_gpio_ids,
> +	.ops		= &gpio_pic32_ops,
> +	.probe		= pic32_gpio_probe,
> +	.priv_auto_alloc_size	= sizeof(struct
> pic32_gpio_priv),
> +};
-- 
- Daniel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 06/14] drivers: serial: add driver for Microchip PIC32 UART controller.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 06/14] drivers: serial: add driver for Microchip PIC32 UART controller Purna Chandra Mandal
@ 2016-01-13 13:49   ` Daniel Schwierzeck
  2016-01-13 14:03     ` Daniel Schwierzeck
  2016-01-13 14:55   ` Tom Rini
  2016-01-13 20:09   ` Simon Glass
  2 siblings, 1 reply; 62+ messages in thread
From: Daniel Schwierzeck @ 2016-01-13 13:49 UTC (permalink / raw)
  To: u-boot

Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra Mandal:
> From: Paul Thacker <paul.thacker@microchip.com>
> 
> This adds PIC32 UART controller support based on driver model.
> 
> Signed-off-by: Paul Thacker <paul.thacker@microchip.com>
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> 

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

nits below

> 
> ---
> 
> Changes in v3:
> - remove ofdata_to_platdata, and replace platdata with priv
> - remove special handling of '\r' as being handled by serial-uclass
> - remove loop to wait for space in tx buffer before pumping char
> 
> Changes in v2:
> - fix missing/corrupted chars during baud rate change
> - remove loop until any char is avaialbale in getc()
> 
>  .../serial/microchip,pic32-uart.txt                |   5 +
>  drivers/serial/Kconfig                             |  13 ++
>  drivers/serial/Makefile                            |   1 +
>  drivers/serial/serial_pic32.c                      | 199
> +++++++++++++++++++++
>  4 files changed, 218 insertions(+)
>  create mode 100644 doc/device-tree-bindings/serial/microchip,pic32
> -uart.txt
>  create mode 100644 drivers/serial/serial_pic32.c
> 
> diff --git a/doc/device-tree-bindings/serial/microchip,pic32-uart.txt
> b/doc/device-tree-bindings/serial/microchip,pic32-uart.txt
> new file mode 100644
> index 0000000..f00e215
> --- /dev/null
> +++ b/doc/device-tree-bindings/serial/microchip,pic32-uart.txt
> @@ -0,0 +1,5 @@
> +* Microchip PIC32 serial UART
> +
> +Required properties:
> +- compatible: must be "microchip,pic32mzda-uart".
> +- reg: exactly one register range.
> diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
> index 1fc287e..9763ea1 100644
> --- a/drivers/serial/Kconfig
> +++ b/drivers/serial/Kconfig
> @@ -107,6 +107,14 @@ config DEBUG_UART_APBUART
>  	  will need to provide parameters to make this work. The
> driver will
>  	  be available until the real driver model serial is
> running.
>  
> +config DEBUG_UART_PIC32
> +	bool "Microchip PIC32"
> +	help
> +	  Select this to enable a debug UART using the serial_pic32
> driver. You
> +	  will need to provide parameters to make this work. The
> driver will
> +	  be available until the real driver model serial is
> running.
> +
> +
>  endchoice
>  
>  config DEBUG_UART_BASE
> @@ -223,4 +231,9 @@ config UNIPHIER_SERIAL
>  	  If you have a UniPhier based board and want to use the on
> -chip
>  	  serial ports, say Y to this option. If unsure, say N.
>  
> +config PIC32_SERIAL
> +	bool "Support for Microchip PIC32 on-chip UART"
> +	help
> +	  Support for the UART found on Microchip PIC32 SoC's.
> +
>  endmenu
> diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
> index dd87147..57cd38b 100644
> --- a/drivers/serial/Makefile
> +++ b/drivers/serial/Makefile
> @@ -41,6 +41,7 @@ obj-$(CONFIG_MXS_AUART) += mxs_auart.o
>  obj-$(CONFIG_ARC_SERIAL) += serial_arc.o
>  obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o
>  obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o
> +obj-$(CONFIG_PIC32_SERIAL) += serial_pic32.o
>  
>  ifndef CONFIG_SPL_BUILD
>  obj-$(CONFIG_USB_TTY) += usbtty.o
> diff --git a/drivers/serial/serial_pic32.c
> b/drivers/serial/serial_pic32.c
> new file mode 100644
> index 0000000..ee9d056
> --- /dev/null
> +++ b/drivers/serial/serial_pic32.c
> @@ -0,0 +1,199 @@
> +/*
> + * (c) 2015 Paul Thacker <paul.thacker@microchip.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + *
> + */
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <serial.h>
> +#include <wait_bit.h>
> +#include <mach/pic32.h>
> +#include <dt-bindings/clock/microchip,clock.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* UART Control Registers */
> +#define U_MOD		0x00
> +#define U_MODCLR	(U_MOD + _CLR_OFFSET)
> +#define U_MODSET	(U_MOD + _SET_OFFSET)
> +#define U_STA		0x10
> +#define U_STACLR	(U_STA + _CLR_OFFSET)
> +#define U_STASET	(U_STA + _SET_OFFSET)
> +#define U_TXR		0x20
> +#define U_RXR		0x30
> +#define U_BRG		0x40
> +
> +/* U_MOD bits */
> +#define UART_ENABLE		BIT(15)
> +
> +/* U_STA bits */
> +#define UART_RX_ENABLE		BIT(12)
> +#define UART_TX_BRK		BIT(11)
> +#define UART_TX_ENABLE		BIT(10)
> +#define UART_TX_FULL		BIT(9)
> +#define UART_TX_EMPTY		BIT(8)
> +#define UART_RX_OERR		BIT(1)
> +#define UART_RX_DATA_AVAIL	BIT(0)
> +
> +struct pic32_uart_priv {
> +	void __iomem *base;
> +	ulong uartclk;
> +};
> +
> +/*
> + * Initialize the serial port with the given baudrate.
> + * The settings are always 8 data bits, no parity, 1 stop bit, no
> start bits.
> + */
> +static int pic32_serial_init(void __iomem *base, ulong clk, u32
> baudrate)
> +{
> +	u32 div = DIV_ROUND_CLOSEST(clk, baudrate * 16);
> +
> +	/* wait for TX FIFO to empty */
> +	wait_for_bit(__func__, base + U_STA, UART_TX_EMPTY,
> +		     true, CONFIG_SYS_HZ, false);
> +
> +	/* send break */
> +	writel(UART_TX_BRK, base + U_STASET);
> +
> +	/* disable and clear mode */
> +	writel(0, base + U_MOD);
> +	writel(0, base + U_STA);
> +
> +	/* set baud rate generator */
> +	writel(div - 1, base + U_BRG);
> +
> +	/* enable the UART for TX and RX */
> +	writel(UART_TX_ENABLE | UART_RX_ENABLE, base + U_STASET);
> +
> +	/* enable the UART */
> +	writel(UART_ENABLE, base + U_MODSET);
> +	return 0;
> +}
> +
> +/* Check number of characters ready in RX Fifo */
> +static int pic32_uart_pending_input(void __iomem *base)
> +{
> +	/* check if rx buffer overrun error has occurred */
> +	if (readl(base + U_STA) & UART_RX_OERR) {
> +		readl(base + U_RXR);
> +
> +		/* clear OERR to keep receiving */
> +		writel(UART_RX_OERR, base + U_STACLR);
> +	}
> +
> +	return readl(base + U_STA) & UART_RX_DATA_AVAIL;
> +}
> +
> +static int pic32_uart_pending(struct udevice *dev, bool input)
> +{
> +	struct pic32_uart_priv *priv = dev_get_priv(dev);
> +
> +	if (input)
> +		return pic32_uart_pending_input(priv->base);
> +
> +	return !(readl(priv->base + U_STA) & UART_TX_EMPTY);
> +}
> +
> +static int pic32_uart_setbrg(struct udevice *dev, int baudrate)
> +{
> +	struct pic32_uart_priv *priv = dev_get_priv(dev);
> +
> +	return pic32_serial_init(priv->base, priv->uartclk,
> baudrate);
> +}
> +
> +static int pic32_uart_putc(struct udevice *dev, const char ch)
> +{
> +	struct pic32_uart_priv *priv = dev_get_priv(dev);
> +
> +	/* Check if Tx FIFO is full */
> +	if (readl(priv->base + U_STA) & UART_TX_FULL)
> +		return -EAGAIN;
> +
> +	/* pump the char to tx buffer */
> +	writel(ch, priv->base + U_TXR);
> +
> +	return 0;
> +}
> +
> +static int pic32_uart_getc(struct udevice *dev)
> +{
> +	struct pic32_uart_priv *priv = dev_get_priv(dev);
> +
> +	/* return error if RX fifo is empty */
> +	if (!pic32_uart_pending_input(priv->base))
> +		return -EAGAIN;
> +
> +	/* read the character from rx buffer */
> +	return readl(priv->base + U_RXR) & 0xff;
> +}
> +
> +static int pic32_uart_probe(struct udevice *dev)
> +{
> +	struct pic32_uart_priv *priv = dev_get_priv(dev);
> +	struct udevice *clkdev;
> +	fdt_addr_t addr;
> +	fdt_size_t size;
> +	int ret;
> +
> +	/* get address */
> +	addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset,
> "reg", &size);
> +	if (addr == FDT_ADDR_T_NONE)
> +		return -EINVAL;
> +
> +	priv->base = ioremap(addr, size);
> +	if (!priv->base)
> +		return -EINVAL;

you can drop this check. ioremap() always returns a mapped address.

> +
> +	/* get clock rate */
> +	ret = uclass_get_device(UCLASS_CLK, 0, &clkdev);
> +	if (ret) {
> +		printf("clk class not found, %d\n", ret);
> +		return ret;
> +	}
> +	priv->uartclk = clk_get_periph_rate(clkdev, PB2CLK);
> +
> +	/* initialize serial */
> +	return pic32_serial_init(priv->base, priv->uartclk,
> CONFIG_BAUDRATE);
> +}
> +
> +static const struct dm_serial_ops pic32_uart_ops = {
> +	.putc		= pic32_uart_putc,
> +	.pending	= pic32_uart_pending,
> +	.getc		= pic32_uart_getc,
> +	.setbrg		= pic32_uart_setbrg,
> +};
> +
> +static const struct udevice_id pic32_uart_ids[] = {
> +	{ .compatible = "microchip,pic32mzda-uart" },
> +	{}
> +};
> +
> +U_BOOT_DRIVER(pic32_serial) = {
> +	.name		= "pic32-uart",
> +	.id		= UCLASS_SERIAL,
> +	.of_match	= pic32_uart_ids,
> +	.probe		= pic32_uart_probe,
> +	.ops		= &pic32_uart_ops,
> +	.flags		= DM_FLAG_PRE_RELOC,
> +	.priv_auto_alloc_size = sizeof(struct pic32_uart_priv),
> +};
> +
> +#ifdef CONFIG_DEBUG_UART_PIC32
> +#include <debug_uart.h>
> +
> +static inline void _debug_uart_init(void)
> +{
> +	void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE;
> +
> +	pic32_serial_init(base, CONFIG_DEBUG_UART_CLOCK,
> CONFIG_BAUDRATE);
> +}
> +
> +static inline void _debug_uart_putc(int ch)
> +{
> +	writel(ch, CONFIG_DEBUG_UART_BASE + U_TXR);
> +}
> +
> +DEBUG_UART_FUNCS
> +#endif
-- 
- Daniel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 07/14] drivers: ddr: Add DDR2 SDRAM controller driver for Microchip PIC32.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 07/14] drivers: ddr: Add DDR2 SDRAM controller driver for Microchip PIC32 Purna Chandra Mandal
@ 2016-01-13 13:53   ` Daniel Schwierzeck
  2016-01-13 14:55   ` Tom Rini
  2016-01-13 20:09   ` Simon Glass
  2 siblings, 0 replies; 62+ messages in thread
From: Daniel Schwierzeck @ 2016-01-13 13:53 UTC (permalink / raw)
  To: u-boot

Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra Mandal:
> This driver initializes PIC32 DDR2 SDRAM controller and internal DDR2
> Phy module.
> DDR2 controller operates in half-rate mode (upto 533MHZ frequency).
> 
> Signed-off-by: Paul Thacker <paul.thacker@microchip.com>
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> 

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

> 
> ---
> 
> Changes in v3:
> - annotating fixed table with const
> - fix camel-case in ddr2 timing parameters
> - fix cmd index parameter of host_load_cmd().
> - fix compilation warning
> 
> Changes in v2:
> - move ddr2 initialization from board/microchip/ to
> drivers/ddr/microchip
> 
>  arch/mips/mach-pic32/include/mach/ddr.h |  32 ++++
>  drivers/Makefile                        |   1 +
>  drivers/ddr/microchip/Makefile          |   6 +
>  drivers/ddr/microchip/ddr2.c            | 278
> ++++++++++++++++++++++++++++++++
>  drivers/ddr/microchip/ddr2_regs.h       | 148 +++++++++++++++++
>  drivers/ddr/microchip/ddr2_timing.h     |  65 ++++++++
>  6 files changed, 530 insertions(+)
>  create mode 100644 arch/mips/mach-pic32/include/mach/ddr.h
>  create mode 100644 drivers/ddr/microchip/Makefile
>  create mode 100644 drivers/ddr/microchip/ddr2.c
>  create mode 100644 drivers/ddr/microchip/ddr2_regs.h
>  create mode 100644 drivers/ddr/microchip/ddr2_timing.h
> 
> diff --git a/arch/mips/mach-pic32/include/mach/ddr.h b/arch/mips/mach
> -pic32/include/mach/ddr.h
> new file mode 100644
> index 0000000..00abfa3
> --- /dev/null
> +++ b/arch/mips/mach-pic32/include/mach/ddr.h
> @@ -0,0 +1,32 @@
> +/*
> + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + *
> + */
> +
> +#ifndef __MICROCHIP_PIC32_DDR_H
> +#define __MICROCHIP_PIC32_DDR_H
> +
> +/* called by initdram() function */
> +void ddr2_phy_init(void);
> +void ddr2_ctrl_init(void);
> +phys_size_t ddr2_calculate_size(void);
> +
> +/* Maximum number of agents */
> +#define NUM_AGENTS		5
> +
> +/* Board can provide agent specific parameters for arbitration by
> + * filling struct ddr2_arbiter_params for all the agents and
> + * implementing board_get_ddr_arbiter_params() to return the filled
> + * structure.
> + */
> +struct ddr2_arbiter_params {
> +	u32 min_limit;	/* min bursts to execute per
> arbitration */
> +	u32 req_period; /* request period threshold for accepted
> cmds */
> +	u32 min_cmd_acpt; /* min number of accepted cmds */
> +};
> +
> +const struct ddr2_arbiter_params
> *board_get_ddr_arbiter_params(void);
> +
> +#endif /* __MICROCHIP_PIC32_DDR_H */
> diff --git a/drivers/Makefile b/drivers/Makefile
> index c9031f2..0ab54d9 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -68,4 +68,5 @@ obj-y += soc/
>  obj-$(CONFIG_REMOTEPROC) += remoteproc/
>  obj-y += thermal/
>  
> +obj-$(CONFIG_MACH_PIC32) += ddr/microchip/
>  endif
> diff --git a/drivers/ddr/microchip/Makefile
> b/drivers/ddr/microchip/Makefile
> new file mode 100644
> index 0000000..305c48b
> --- /dev/null
> +++ b/drivers/ddr/microchip/Makefile
> @@ -0,0 +1,6 @@
> +#
> +# Copyright (C) 2015 Microchip Technology Inc.
> +#
> +# SPDX-License-Identifier:	GPL-2.0+
> +#
> +obj-$(CONFIG_MACH_PIC32) += ddr2.o
> diff --git a/drivers/ddr/microchip/ddr2.c
> b/drivers/ddr/microchip/ddr2.c
> new file mode 100644
> index 0000000..6056418
> --- /dev/null
> +++ b/drivers/ddr/microchip/ddr2.c
> @@ -0,0 +1,278 @@
> +/*
> + * (c) 2015 Paul Thacker <paul.thacker@microchip.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + *
> + */
> +#include <common.h>
> +#include <wait_bit.h>
> +#include <linux/kernel.h>
> +#include <linux/bitops.h>
> +#include <mach/pic32.h>
> +#include <mach/ddr.h>
> +
> +#include "ddr2_regs.h"
> +#include "ddr2_timing.h"
> +
> +/* init DDR2 Phy */
> +void ddr2_phy_init(void)
> +{
> +	struct ddr2_phy_regs *ddr2_phy;
> +	u32 pad_ctl;
> +
> +	ddr2_phy = ioremap(PIC32_DDR2P_BASE, sizeof(*ddr2_phy));
> +
> +	/* PHY_DLL_RECALIB */
> +	writel(DELAY_START_VAL(3) | DISABLE_RECALIB(0) |
> +	       RECALIB_CNT(0x10), &ddr2_phy->dll_recalib);
> +
> +	/* PHY_PAD_CTRL */
> +	pad_ctl = ODT_SEL | ODT_EN | DRIVE_SEL(0) |
> +		  ODT_PULLDOWN(2) | ODT_PULLUP(3) |
> +		  EXTRA_OEN_CLK(0) | NOEXT_DLL |
> +		  DLR_DFT_WRCMD | HALF_RATE |
> +		  DRVSTR_PFET(0xe) | DRVSTR_NFET(0xe) |
> +		  RCVR_EN | PREAMBLE_DLY(2);
> +	writel(pad_ctl, &ddr2_phy->pad_ctrl);
> +
> +	/* SCL_CONFIG_0 */
> +	writel(SCL_BURST8 | SCL_DDR_CONNECTED | SCL_RCAS_LAT(RL) |
> +	       SCL_ODTCSWW, &ddr2_phy->scl_config_1);
> +
> +	/* SCL_CONFIG_1 */
> +	writel(SCL_CSEN | SCL_WCAS_LAT(WL), &ddr2_phy
> ->scl_config_2);
> +
> +	/* SCL_LAT */
> +	writel(SCL_CAPCLKDLY(3) | SCL_DDRCLKDLY(4), &ddr2_phy
> ->scl_latency);
> +}
> +
> +/* start phy self calibration logic */
> +static int ddr2_phy_calib_start(void)
> +{
> +	struct ddr2_phy_regs *ddr2_phy;
> +
> +	ddr2_phy = ioremap(PIC32_DDR2P_BASE, sizeof(*ddr2_phy));
> +
> +	/* DDR Phy SCL Start */
> +	writel(SCL_START | SCL_EN, &ddr2_phy->scl_start);
> +
> +	/* Wait for SCL for data byte to pass */
> +	return wait_for_bit(__func__, &ddr2_phy->scl_start,
> SCL_LUBPASS,
> +			    true, CONFIG_SYS_HZ, false);
> +}
> +
> +/* DDR2 Controller initialization */
> +
> +/* Target Agent Arbiter */
> +static void ddr_set_arbiter(struct ddr2_ctrl_regs *ctrl,
> +			    const struct ddr2_arbiter_params *const
> param)
> +{
> +	int i;
> +
> +	for (i = 0; i < NUM_AGENTS; i++) {
> +		/* set min burst size */
> +		writel(i * MIN_LIM_WIDTH, &ctrl->tsel);
> +		writel(param->min_limit, &ctrl->minlim);
> +
> +		/* set request period (4 * req_period clocks) */
> +		writel(i * RQST_PERIOD_WIDTH, &ctrl->tsel);
> +		writel(param->req_period, &ctrl->reqprd);
> +
> +		/* set number of burst accepted */
> +		writel(i * MIN_CMDACPT_WIDTH, &ctrl->tsel);
> +		writel(param->min_cmd_acpt, &ctrl->mincmd);
> +	}
> +}
> +
> +const struct ddr2_arbiter_params *__weak
> board_get_ddr_arbiter_params(void)
> +{
> +	/* default arbiter parameters */
> +	static const struct ddr2_arbiter_params arb_params[] = {
> +		{ .min_limit = 0x1f, .req_period = 0xff,
> .min_cmd_acpt = 0x04,},
> +		{ .min_limit = 0x1f, .req_period = 0xff,
> .min_cmd_acpt = 0x10,},
> +		{ .min_limit = 0x1f, .req_period = 0xff,
> .min_cmd_acpt = 0x10,},
> +		{ .min_limit = 0x04, .req_period = 0xff,
> .min_cmd_acpt = 0x04,},
> +		{ .min_limit = 0x04, .req_period = 0xff,
> .min_cmd_acpt = 0x04,},
> +	};
> +
> +	return &arb_params[0];
> +}
> +
> +static void host_load_cmd(struct ddr2_ctrl_regs *ctrl, u32 cmd_idx,
> +			  u32 hostcmd2, u32 hostcmd1, u32 delay)
> +{
> +	u32 hc_delay;
> +
> +	hc_delay = max_t(u32, DIV_ROUND_UP(delay, T_CK), 2) - 2;
> +	writel(hostcmd1, &ctrl->cmd10[cmd_idx]);
> +	writel((hostcmd2 & 0x7ff) | (hc_delay << 11), &ctrl
> ->cmd20[cmd_idx]);
> +}
> +
> +/* init DDR2 Controller */
> +void ddr2_ctrl_init(void)
> +{
> +	u32 wr2prech, rd2prech, wr2rd, wr2rd_cs;
> +	u32 ras2ras, ras2cas, prech2ras, temp;
> +	const struct ddr2_arbiter_params *arb_params;
> +	struct ddr2_ctrl_regs *ctrl;
> +
> +	ctrl = ioremap(PIC32_DDR2C_BASE, sizeof(*ctrl));
> +
> +	/* PIC32 DDR2 controller always work in HALF_RATE */
> +	writel(HALF_RATE_MODE, &ctrl->memwidth);
> +
> +	/* Set arbiter configuration per target */
> +	arb_params = board_get_ddr_arbiter_params();
> +	ddr_set_arbiter(ctrl, arb_params);
> +
> +	/* Address Configuration, model {CS, ROW, BA, COL} */
> +	writel((ROW_ADDR_RSHIFT | (BA_RSHFT << 8) | (CS_ADDR_RSHIFT
> << 16) |
> +	       (COL_HI_RSHFT << 24) | (SB_PRI << 29)  |
> +	       (EN_AUTO_PRECH << 30)), &ctrl->memcfg0);
> +
> +	writel(ROW_ADDR_MASK, &ctrl->memcfg1);
> +	writel(COL_HI_MASK, &ctrl->memcfg2);
> +	writel(COL_LO_MASK, &ctrl->memcfg3);
> +	writel(BA_MASK | (CS_ADDR_MASK << 8), &ctrl->memcfg4);
> +
> +	/* Refresh Config */
> +	writel(REFCNT_CLK(DIV_ROUND_UP(T_RFI, T_CK_CTRL) - 2) |
> +	       REFDLY_CLK(DIV_ROUND_UP(T_RFC_MIN, T_CK_CTRL) - 2) |
> +	       MAX_PEND_REF(7),
> +	       &ctrl->refcfg);
> +
> +	/* Power Config */
> +	writel(ECC_EN(0) | ERR_CORR_EN(0) | EN_AUTO_PWR_DN(0) |
> +	       EN_AUTO_SELF_REF(3) | PWR_DN_DLY(8) |
> +	       SELF_REF_DLY(17) | PRECH_PWR_DN_ONLY(0),
> +	       &ctrl->pwrcfg);
> +
> +	/* Delay Config */
> +	wr2rd = max_t(u32, DIV_ROUND_UP(T_WTR, T_CK_CTRL),
> +		      DIV_ROUND_UP(T_WTR_TCK, 2)) + WL + BL;
> +	wr2rd_cs = max_t(u32, wr2rd - 1, 3);
> +	wr2prech = DIV_ROUND_UP(T_WR, T_CK_CTRL) + WL + BL;
> +	rd2prech = max_t(u32, DIV_ROUND_UP(T_RTP, T_CK_CTRL),
> +			 DIV_ROUND_UP(T_RTP_TCK, 2)) + BL - 2;
> +	ras2ras = max_t(u32, DIV_ROUND_UP(T_RRD, T_CK_CTRL),
> +			DIV_ROUND_UP(T_RRD_TCK, 2)) - 1;
> +	ras2cas = DIV_ROUND_UP(T_RCD, T_CK_CTRL) - 1;
> +	prech2ras = DIV_ROUND_UP(T_RP, T_CK_CTRL) - 1;
> +
> +	writel(((wr2rd & 0x0f) |
> +	       ((wr2rd_cs & 0x0f) << 4) |
> +	       ((BL - 1) << 8) |
> +	       (BL << 12) |
> +	       ((BL - 1) << 16) |
> +	       ((BL - 1) << 20) |
> +	       ((BL + 2) << 24) |
> +	       ((RL - WL + 3) << 28)), &ctrl->dlycfg0);
> +
> +	writel(((T_CKE_TCK - 1) |
> +	       (((DIV_ROUND_UP(T_DLLK, 2) - 2) & 0xff) << 8) |
> +	       ((T_CKE_TCK - 1) << 16) |
> +	       ((max_t(u32, T_XP_TCK, T_CKE_TCK) - 1) << 20) |
> +	       ((wr2prech >> 4) << 26) |
> +	       ((wr2rd >> 4) << 27) |
> +	       ((wr2rd_cs >> 4) << 28) |
> +	       (((RL + 5) >> 4) << 29) |
> +	       ((DIV_ROUND_UP(T_DLLK, 2) >> 8) << 30)), &ctrl
> ->dlycfg1);
> +
> +	writel((DIV_ROUND_UP(T_RP, T_CK_CTRL) |
> +	       (rd2prech << 8) |
> +	       ((wr2prech & 0x0f) << 12) |
> +	       (ras2ras << 16) |
> +	       (ras2cas << 20) |
> +	       (prech2ras << 24) |
> +	       ((RL + 3) << 28)), &ctrl->dlycfg2);
> +
> +	writel(((DIV_ROUND_UP(T_RAS_MIN, T_CK_CTRL) - 1) |
> +	       ((DIV_ROUND_UP(T_RC, T_CK_CTRL) - 1) << 8) |
> +	       ((DIV_ROUND_UP(T_FAW, T_CK_CTRL) - 1) << 16)),
> +	       &ctrl->dlycfg3);
> +
> +	/* ODT Config */
> +	writel(0x0, &ctrl->odtcfg);
> +	writel(BIT(16), &ctrl->odtencfg);
> +	writel(ODTRDLY(RL - 3) | ODTWDLY(WL - 3) | ODTRLEN(2) |
> ODTWLEN(3),
> +	       &ctrl->odtcfg);
> +
> +	/* Transfer Configuration */
> +	writel(NXTDATRQDLY(2) | NXDATAVDLY(4) | RDATENDLY(2) |
> +	       MAX_BURST(3) | (7 << 28) | BIG_ENDIAN(0),
> +	       &ctrl->xfercfg);
> +
> +	/* DRAM Initialization */
> +	/* CKE high after reset and wait 400 nsec */
> +	host_load_cmd(ctrl, 0, 0, IDLE_NOP, 400000);
> +
> +	/* issue precharge all command */
> +	host_load_cmd(ctrl, 1, 0x04, PRECH_ALL_CMD, T_RP + T_CK);
> +
> +	/* initialize EMR2 */
> +	host_load_cmd(ctrl, 2, 0x200, LOAD_MODE_CMD, T_MRD_TCK *
> T_CK);
> +
> +	/* initialize EMR3 */
> +	host_load_cmd(ctrl, 3, 0x300, LOAD_MODE_CMD, T_MRD_TCK *
> T_CK);
> +
> +	/*
> +	 * RDQS disable, DQSB enable, OCD exit, 150 ohm termination,
> +	 * AL=0, DLL enable
> +	 */
> +	host_load_cmd(ctrl, 4, 0x100,
> +		      LOAD_MODE_CMD | (0x40 << 24), T_MRD_TCK *
> T_CK);
> +	/*
> +	 * PD fast exit, WR REC = T_WR in clocks -1,
> +	 * DLL reset, CAS = RL, burst = 4
> +	 */
> +	temp = ((DIV_ROUND_UP(T_WR, T_CK) - 1) << 1) | 1;
> +	host_load_cmd(ctrl, 5, temp, LOAD_MODE_CMD | (RL << 28) | (2
> << 24),
> +		      T_MRD_TCK * T_CK);
> +
> +	/* issue precharge all command */
> +	host_load_cmd(ctrl, 6, 4, PRECH_ALL_CMD, T_RP + T_CK);
> +
> +	/* issue refresh command */
> +	host_load_cmd(ctrl, 7, 0, REF_CMD, T_RFC_MIN);
> +
> +	/* issue refresh command */
> +	host_load_cmd(ctrl, 8, 0, REF_CMD, T_RFC_MIN);
> +
> +	/* Mode register programming as before without DLL reset */
> +	host_load_cmd(ctrl, 9, temp, LOAD_MODE_CMD | (RL << 28) | (3
> << 24),
> +		      T_MRD_TCK * T_CK);
> +
> +	/* extended mode register same as before with OCD default */
> +	host_load_cmd(ctrl, 10, 0x103, LOAD_MODE_CMD | (0xc << 24),
> +		      T_MRD_TCK * T_CK);
> +
> +	/* extended mode register same as before with OCD exit */
> +	host_load_cmd(ctrl, 11, 0x100, LOAD_MODE_CMD | (0x4 << 28),
> +		      140 * T_CK);
> +
> +	writel(CMD_VALID | NUMHOSTCMD(11), &ctrl->cmdissue);
> +
> +	/* start memory initialization */
> +	writel(INIT_START, &ctrl->memcon);
> +
> +	/* wait for all host cmds to be transmitted */
> +	wait_for_bit(__func__, &ctrl->cmdissue, CMD_VALID, false,
> +		     CONFIG_SYS_HZ, false);
> +
> +	/* inform all cmds issued, ready for normal operation */
> +	writel(INIT_START | INIT_DONE, &ctrl->memcon);
> +
> +	/* perform phy caliberation */
> +	if (ddr2_phy_calib_start())
> +		printf("ddr2: phy calib failed\n");
> +}
> +
> +phys_size_t ddr2_calculate_size(void)
> +{
> +	u32 temp;
> +
> +	temp = 1 << (COL_BITS + BA_BITS + ROW_BITS);
> +	/* 16-bit data width between controller and DIMM */
> +	temp = temp * CS_BITS * (16 / 8);
> +	return (phys_size_t)temp;
> +}
> diff --git a/drivers/ddr/microchip/ddr2_regs.h
> b/drivers/ddr/microchip/ddr2_regs.h
> new file mode 100644
> index 0000000..0f4b159
> --- /dev/null
> +++ b/drivers/ddr/microchip/ddr2_regs.h
> @@ -0,0 +1,148 @@
> +/*
> + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + *
> + */
> +
> +#ifndef __MICROCHIP_DDR2_REGS_H
> +#define __MICROCHIP_DDR2_REGS_H
> +
> +#include <linux/bitops.h>
> +
> +/* DDR2 Controller */
> +struct ddr2_ctrl_regs {
> +	u32 tsel;
> +	u32 minlim;
> +	u32 reqprd;
> +	u32 mincmd;
> +	u32 memcon;
> +	u32 memcfg0;
> +	u32 memcfg1;
> +	u32 memcfg2;
> +	u32 memcfg3;
> +	u32 memcfg4;
> +	u32 refcfg;
> +	u32 pwrcfg;
> +	u32 dlycfg0;
> +	u32 dlycfg1;
> +	u32 dlycfg2;
> +	u32 dlycfg3;
> +	u32 odtcfg;
> +	u32 xfercfg;
> +	u32 cmdissue;
> +	u32 odtencfg;
> +	u32 memwidth;
> +	u32 unused[11];
> +	u32 cmd10[16];
> +	u32 cmd20[16];
> +};
> +
> +/* Arbiter Config */
> +#define MIN_LIM_WIDTH		5
> +#define RQST_PERIOD_WIDTH	8
> +#define MIN_CMDACPT_WIDTH	8
> +
> +/* Refresh Config */
> +#define REFCNT_CLK(x)		(x)
> +#define REFDLY_CLK(x)		((x) << 16)
> +#define MAX_PEND_REF(x)		((x) << 24)
> +
> +/* Power Config */
> +#define PRECH_PWR_DN_ONLY(x)	((x) << 22)
> +#define SELF_REF_DLY(x)		((x) << 12)
> +#define PWR_DN_DLY(x)		((x) << 4)
> +#define EN_AUTO_SELF_REF(x)	((x) << 3)
> +#define EN_AUTO_PWR_DN(x)	((x) << 2)
> +#define ERR_CORR_EN(x)		((x) << 1)
> +#define ECC_EN(x)		(x)
> +
> +/* Memory Width */
> +#define HALF_RATE_MODE		BIT(3)
> +
> +/* Delay Config */
> +#define ODTWLEN(x)	((x) << 20)
> +#define ODTRLEN(x)	((x) << 16)
> +#define ODTWDLY(x)	((x) << 12)
> +#define ODTRDLY(x)	((x) << 8)
> +
> +/* Xfer Config */
> +#define BIG_ENDIAN(x)	((x) << 31)
> +#define MAX_BURST(x)	((x) << 24)
> +#define RDATENDLY(x)	((x) << 16)
> +#define NXDATAVDLY(x)	((x) << 4)
> +#define NXTDATRQDLY(x)	((x) << 0)
> +
> +/* Host Commands */
> +#define IDLE_NOP	0x00ffffff
> +#define PRECH_ALL_CMD	0x00fff401
> +#define REF_CMD		0x00fff801
> +#define LOAD_MODE_CMD	0x00fff001
> +#define CKE_LOW		0x00ffeffe
> +
> +#define NUM_HOST_CMDS	12
> +
> +/* Host CMD Issue */
> +#define CMD_VALID	BIT(4)
> +#define NUMHOSTCMD(x)	(x)
> +
> +/* Memory Control */
> +#define INIT_DONE	BIT(1)
> +#define INIT_START	BIT(0)
> +
> +/* Address Control */
> +#define EN_AUTO_PRECH		0
> +#define SB_PRI			1
> +
> +/* DDR2 Phy Register */
> +struct ddr2_phy_regs {
> +	u32 scl_start;
> +	u32 unused1[2];
> +	u32 scl_latency;
> +	u32 unused2[2];
> +	u32 scl_config_1;
> +	u32 scl_config_2;
> +	u32 pad_ctrl;
> +	u32 dll_recalib;
> +};
> +
> +/* PHY PAD CONTROL */
> +#define ODT_SEL			BIT(0)
> +#define ODT_EN			BIT(1)
> +#define DRIVE_SEL(x)		((x) << 2)
> +#define ODT_PULLDOWN(x)		((x) << 4)
> +#define ODT_PULLUP(x)		((x) << 6)
> +#define EXTRA_OEN_CLK(x)	((x) << 8)
> +#define NOEXT_DLL		BIT(9)
> +#define DLR_DFT_WRCMD		BIT(13)
> +#define HALF_RATE		BIT(14)
> +#define DRVSTR_PFET(x)		((x) << 16)
> +#define DRVSTR_NFET(x)		((x) << 20)
> +#define RCVR_EN			BIT(28)
> +#define PREAMBLE_DLY(x)		((x) << 29)
> +
> +/* PHY DLL RECALIBRATE */
> +#define RECALIB_CNT(x)		((x) << 8)
> +#define DISABLE_RECALIB(x)	((x) << 26)
> +#define DELAY_START_VAL(x)	((x) << 28)
> +
> +/* PHY SCL CONFIG1 */
> +#define SCL_BURST8		BIT(0)
> +#define SCL_DDR_CONNECTED		BIT(1)
> +#define SCL_RCAS_LAT(x)		((x) << 4)
> +#define SCL_ODTCSWW		BIT(24)
> +
> +/* PHY SCL CONFIG2 */
> +#define SCL_CSEN		BIT(0)
> +#define SCL_WCAS_LAT(x)		((x) << 8)
> +
> +/* PHY SCL Latency */
> +#define SCL_CAPCLKDLY(x)	((x) << 0)
> +#define SCL_DDRCLKDLY(x)	((x) << 4)
> +
> +/* PHY SCL START */
> +#define SCL_START		BIT(28)
> +#define SCL_EN			BIT(26)
> +#define SCL_LUBPASS		(BIT(1) | BIT(0))
> +
> +#endif	/* __MICROCHIP_DDR2_REGS_H */
> diff --git a/drivers/ddr/microchip/ddr2_timing.h
> b/drivers/ddr/microchip/ddr2_timing.h
> new file mode 100644
> index 0000000..5895f9d
> --- /dev/null
> +++ b/drivers/ddr/microchip/ddr2_timing.h
> @@ -0,0 +1,65 @@
> +/*
> + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + *
> + */
> +
> +#ifndef __MICROCHIP_DDR2_TIMING_H
> +#define __MICROCHIP_DDR2_TIMING_H
> +
> +/* MPLL freq is 400MHz */
> +#define T_CK		2500    /* 2500 psec */
> +#define T_CK_CTRL	(T_CK * 2)
> +
> +/* Burst length in cycles */
> +#define BL		2
> +/* default CAS latency for all speed grades */
> +#define RL		5
> +/* default write latency for all speed grades = CL-1 */
> +#define WL		4
> +
> +/* From Micron MT47H64M16HR-3 data sheet */
> +#define T_RFC_MIN	127500	/* psec */
> +#define T_WR		15000	/* psec */
> +#define T_RP		12500	/* psec */
> +#define T_RCD		12500	/* psec */
> +#define T_RRD		7500	/* psec */
> +/* T_RRD_TCK is minimum of 2 clk periods, regardless of freq */
> +#define T_RRD_TCK	2
> +#define T_WTR		7500	/* psec */
> +/* T_WTR_TCK is minimum of 2 clk periods, regardless of freq */
> +#define T_WTR_TCK	2
> +#define T_RTP		7500	/* psec */
> +#define T_RTP_TCK	(BL / 2)
> +#define T_XP_TCK	2	/* clocks */
> +#define T_CKE_TCK	3	/* clocks */
> +#define T_XSNR		(T_RFC_MIN + 10000) /* psec */
> +#define T_DLLK		200     /* clocks */
> +#define T_RAS_MIN	45000   /* psec */
> +#define T_RC		57500   /* psec */
> +#define T_FAW		35000   /* psec */
> +#define T_MRD_TCK	2       /* clocks */
> +#define T_RFI		7800000 /* psec */
> +
> +/* DDR Addressing */
> +#define COL_BITS	10
> +#define BA_BITS		3
> +#define ROW_BITS	13
> +#define CS_BITS		1
> +
> +/* DDR Addressing scheme: {CS, ROW, BA, COL} */
> +#define COL_HI_RSHFT	0
> +#define COL_HI_MASK	0
> +#define COL_LO_MASK	((1 << COL_BITS) - 1)
> +
> +#define BA_RSHFT	COL_BITS
> +#define BA_MASK		((1 << BA_BITS) - 1)
> +
> +#define ROW_ADDR_RSHIFT	(BA_RSHFT + BA_BITS)
> +#define ROW_ADDR_MASK	((1 << ROW_BITS) - 1)
> +
> +#define CS_ADDR_RSHIFT	0
> +#define CS_ADDR_MASK	0
> +
> +#endif	/* __MICROCHIP_DDR2_TIMING_H */
-- 
- Daniel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 06/14] drivers: serial: add driver for Microchip PIC32 UART controller.
  2016-01-13 13:49   ` Daniel Schwierzeck
@ 2016-01-13 14:03     ` Daniel Schwierzeck
  2016-01-14  5:42       ` Purna Chandra Mandal
  0 siblings, 1 reply; 62+ messages in thread
From: Daniel Schwierzeck @ 2016-01-13 14:03 UTC (permalink / raw)
  To: u-boot

Am Mittwoch, den 13.01.2016, 14:49 +0100 schrieb Daniel Schwierzeck:
> Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra
> Mandal:
> > From: Paul Thacker <paul.thacker@microchip.com>
> > 
> > This adds PIC32 UART controller support based on driver model.
> > 
> > Signed-off-by: Paul Thacker <paul.thacker@microchip.com>
> > Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> > 
> 
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
> 
> nits below

I forgot one thing

> 
> > 
> > ---
> > 
> > Changes in v3:
> > - remove ofdata_to_platdata, and replace platdata with priv
> > - remove special handling of '\r' as being handled by serial-uclass
> > - remove loop to wait for space in tx buffer before pumping char
> > 
> > Changes in v2:
> > - fix missing/corrupted chars during baud rate change
> > - remove loop until any char is avaialbale in getc()
> > 
> >  .../serial/microchip,pic32-uart.txt                |   5 +
> >  drivers/serial/Kconfig                             |  13 ++
> >  drivers/serial/Makefile                            |   1 +
> >  drivers/serial/serial_pic32.c                      | 199
> > +++++++++++++++++++++
> >  4 files changed, 218 insertions(+)
> >  create mode 100644 doc/device-tree-bindings/serial/microchip,pic32
> > -uart.txt
> >  create mode 100644 drivers/serial/serial_pic32.c
> > 
> > diff --git a/doc/device-tree-bindings/serial/microchip,pic32
> > -uart.txt
> > b/doc/device-tree-bindings/serial/microchip,pic32-uart.txt
> > new file mode 100644
> > index 0000000..f00e215
> > --- /dev/null
> > +++ b/doc/device-tree-bindings/serial/microchip,pic32-uart.txt
> > @@ -0,0 +1,5 @@
> > +* Microchip PIC32 serial UART
> > +
> > +Required properties:
> > +- compatible: must be "microchip,pic32mzda-uart".
> > +- reg: exactly one register range.
> > diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
> > index 1fc287e..9763ea1 100644
> > --- a/drivers/serial/Kconfig
> > +++ b/drivers/serial/Kconfig
> > @@ -107,6 +107,14 @@ config DEBUG_UART_APBUART
> >  	  will need to provide parameters to make this work. The
> > driver will
> >  	  be available until the real driver model serial is
> > running.
> >  
> > +config DEBUG_UART_PIC32
> > +	bool "Microchip PIC32"
> > +	help
> > +	  Select this to enable a debug UART using the
> > serial_pic32
> > driver. You
> > +	  will need to provide parameters to make this work. The
> > driver will
> > +	  be available until the real driver model serial is
> > running.
> > +
> > +
> >  endchoice
> >  
> >  config DEBUG_UART_BASE
> > @@ -223,4 +231,9 @@ config UNIPHIER_SERIAL
> >  	  If you have a UniPhier based board and want to use the
> > on
> > -chip
> >  	  serial ports, say Y to this option. If unsure, say N.
> >  
> > +config PIC32_SERIAL
> > +	bool "Support for Microchip PIC32 on-chip UART"

you should add

depends on DM_SERIAL && MACH_PIC32

> > +	help
> > +	  Support for the UART found on Microchip PIC32 SoC's.
> > +
> >  endmenu
> > diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
> > index dd87147..57cd38b 100644
> > --- a/drivers/serial/Makefile
> > +++ b/drivers/serial/Makefile
> > @@ -41,6 +41,7 @@ obj-$(CONFIG_MXS_AUART) += mxs_auart.o
> >  obj-$(CONFIG_ARC_SERIAL) += serial_arc.o
> >  obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o
> >  obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o
> > +obj-$(CONFIG_PIC32_SERIAL) += serial_pic32.o
> >  
> >  ifndef CONFIG_SPL_BUILD
> >  obj-$(CONFIG_USB_TTY) += usbtty.o
> > diff --git a/drivers/serial/serial_pic32.c
> > b/drivers/serial/serial_pic32.c
> > new file mode 100644
> > index 0000000..ee9d056
> > --- /dev/null
> > +++ b/drivers/serial/serial_pic32.c
> > @@ -0,0 +1,199 @@
> > +/*
> > + * (c) 2015 Paul Thacker <paul.thacker@microchip.com>
> > + *
> > + * SPDX-License-Identifier:	GPL-2.0+
> > + *
> > + */
> > +#include <common.h>
> > +#include <clk.h>
> > +#include <dm.h>
> > +#include <serial.h>
> > +#include <wait_bit.h>
> > +#include <mach/pic32.h>
> > +#include <dt-bindings/clock/microchip,clock.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +/* UART Control Registers */
> > +#define U_MOD		0x00
> > +#define U_MODCLR	(U_MOD + _CLR_OFFSET)
> > +#define U_MODSET	(U_MOD + _SET_OFFSET)
> > +#define U_STA		0x10
> > +#define U_STACLR	(U_STA + _CLR_OFFSET)
> > +#define U_STASET	(U_STA + _SET_OFFSET)
> > +#define U_TXR		0x20
> > +#define U_RXR		0x30
> > +#define U_BRG		0x40
> > +
> > +/* U_MOD bits */
> > +#define UART_ENABLE		BIT(15)
> > +
> > +/* U_STA bits */
> > +#define UART_RX_ENABLE		BIT(12)
> > +#define UART_TX_BRK		BIT(11)
> > +#define UART_TX_ENABLE		BIT(10)
> > +#define UART_TX_FULL		BIT(9)
> > +#define UART_TX_EMPTY		BIT(8)
> > +#define UART_RX_OERR		BIT(1)
> > +#define UART_RX_DATA_AVAIL	BIT(0)
> > +
> > +struct pic32_uart_priv {
> > +	void __iomem *base;
> > +	ulong uartclk;
> > +};
> > +
> > +/*
> > + * Initialize the serial port with the given baudrate.
> > + * The settings are always 8 data bits, no parity, 1 stop bit, no
> > start bits.
> > + */
> > +static int pic32_serial_init(void __iomem *base, ulong clk, u32
> > baudrate)
> > +{
> > +	u32 div = DIV_ROUND_CLOSEST(clk, baudrate * 16);
> > +
> > +	/* wait for TX FIFO to empty */
> > +	wait_for_bit(__func__, base + U_STA, UART_TX_EMPTY,
> > +		     true, CONFIG_SYS_HZ, false);
> > +
> > +	/* send break */
> > +	writel(UART_TX_BRK, base + U_STASET);
> > +
> > +	/* disable and clear mode */
> > +	writel(0, base + U_MOD);
> > +	writel(0, base + U_STA);
> > +
> > +	/* set baud rate generator */
> > +	writel(div - 1, base + U_BRG);
> > +
> > +	/* enable the UART for TX and RX */
> > +	writel(UART_TX_ENABLE | UART_RX_ENABLE, base + U_STASET);
> > +
> > +	/* enable the UART */
> > +	writel(UART_ENABLE, base + U_MODSET);
> > +	return 0;
> > +}
> > +
> > +/* Check number of characters ready in RX Fifo */
> > +static int pic32_uart_pending_input(void __iomem *base)
> > +{
> > +	/* check if rx buffer overrun error has occurred */
> > +	if (readl(base + U_STA) & UART_RX_OERR) {
> > +		readl(base + U_RXR);
> > +
> > +		/* clear OERR to keep receiving */
> > +		writel(UART_RX_OERR, base + U_STACLR);
> > +	}
> > +
> > +	return readl(base + U_STA) & UART_RX_DATA_AVAIL;
> > +}
> > +
> > +static int pic32_uart_pending(struct udevice *dev, bool input)
> > +{
> > +	struct pic32_uart_priv *priv = dev_get_priv(dev);
> > +
> > +	if (input)
> > +		return pic32_uart_pending_input(priv->base);
> > +
> > +	return !(readl(priv->base + U_STA) & UART_TX_EMPTY);
> > +}
> > +
> > +static int pic32_uart_setbrg(struct udevice *dev, int baudrate)
> > +{
> > +	struct pic32_uart_priv *priv = dev_get_priv(dev);
> > +
> > +	return pic32_serial_init(priv->base, priv->uartclk,
> > baudrate);
> > +}
> > +
> > +static int pic32_uart_putc(struct udevice *dev, const char ch)
> > +{
> > +	struct pic32_uart_priv *priv = dev_get_priv(dev);
> > +
> > +	/* Check if Tx FIFO is full */
> > +	if (readl(priv->base + U_STA) & UART_TX_FULL)
> > +		return -EAGAIN;
> > +
> > +	/* pump the char to tx buffer */
> > +	writel(ch, priv->base + U_TXR);
> > +
> > +	return 0;
> > +}
> > +
> > +static int pic32_uart_getc(struct udevice *dev)
> > +{
> > +	struct pic32_uart_priv *priv = dev_get_priv(dev);
> > +
> > +	/* return error if RX fifo is empty */
> > +	if (!pic32_uart_pending_input(priv->base))
> > +		return -EAGAIN;
> > +
> > +	/* read the character from rx buffer */
> > +	return readl(priv->base + U_RXR) & 0xff;
> > +}
> > +
> > +static int pic32_uart_probe(struct udevice *dev)
> > +{
> > +	struct pic32_uart_priv *priv = dev_get_priv(dev);
> > +	struct udevice *clkdev;
> > +	fdt_addr_t addr;
> > +	fdt_size_t size;
> > +	int ret;
> > +
> > +	/* get address */
> > +	addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset,
> > "reg", &size);
> > +	if (addr == FDT_ADDR_T_NONE)
> > +		return -EINVAL;
> > +
> > +	priv->base = ioremap(addr, size);
> > +	if (!priv->base)
> > +		return -EINVAL;
> 
> you can drop this check. ioremap() always returns a mapped address.
> 
> > +
> > +	/* get clock rate */
> > +	ret = uclass_get_device(UCLASS_CLK, 0, &clkdev);
> > +	if (ret) {
> > +		printf("clk class not found, %d\n", ret);
> > +		return ret;
> > +	}
> > +	priv->uartclk = clk_get_periph_rate(clkdev, PB2CLK);
> > +
> > +	/* initialize serial */
> > +	return pic32_serial_init(priv->base, priv->uartclk,
> > CONFIG_BAUDRATE);
> > +}
> > +
> > +static const struct dm_serial_ops pic32_uart_ops = {
> > +	.putc		= pic32_uart_putc,
> > +	.pending	= pic32_uart_pending,
> > +	.getc		= pic32_uart_getc,
> > +	.setbrg		= pic32_uart_setbrg,
> > +};
> > +
> > +static const struct udevice_id pic32_uart_ids[] = {
> > +	{ .compatible = "microchip,pic32mzda-uart" },
> > +	{}
> > +};
> > +
> > +U_BOOT_DRIVER(pic32_serial) = {
> > +	.name		= "pic32-uart",
> > +	.id		= UCLASS_SERIAL,
> > +	.of_match	= pic32_uart_ids,
> > +	.probe		= pic32_uart_probe,
> > +	.ops		= &pic32_uart_ops,
> > +	.flags		= DM_FLAG_PRE_RELOC,
> > +	.priv_auto_alloc_size = sizeof(struct pic32_uart_priv),
> > +};
> > +
> > +#ifdef CONFIG_DEBUG_UART_PIC32
> > +#include <debug_uart.h>
> > +
> > +static inline void _debug_uart_init(void)
> > +{
> > +	void __iomem *base = (void __iomem
> > *)CONFIG_DEBUG_UART_BASE;
> > +
> > +	pic32_serial_init(base, CONFIG_DEBUG_UART_CLOCK,
> > CONFIG_BAUDRATE);
> > +}
> > +
> > +static inline void _debug_uart_putc(int ch)
> > +{
> > +	writel(ch, CONFIG_DEBUG_UART_BASE + U_TXR);
> > +}
> > +
> > +DEBUG_UART_FUNCS
> > +#endif
-- 
- Daniel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 05/14] drivers: gpio: add driver for Microchip PIC32 GPIO controller.
  2016-01-13 13:46   ` Daniel Schwierzeck
@ 2016-01-13 14:08     ` Daniel Schwierzeck
  2016-01-14  5:41       ` Purna Chandra Mandal
  0 siblings, 1 reply; 62+ messages in thread
From: Daniel Schwierzeck @ 2016-01-13 14:08 UTC (permalink / raw)
  To: u-boot

Am Mittwoch, den 13.01.2016, 14:46 +0100 schrieb Daniel Schwierzeck:
> Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra
> Mandal:
> > In PIC32 GPIO controller is part of PIC32 pin controller.
> > PIC32 has ten independently programmable ports and each with
> > multiple
> > pins.
> > Each of these pins can be configured and used as GPIO, provided
> > they
> > are not in use for other peripherals.
> > 
> > Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> 
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
> 
> nits below
> 
> > 
> > ---
> > 
> > Changes in v3:
> > - add check on dev_get_addr()
> > 
> > Changes in v2: None
> > 
> >  drivers/gpio/Kconfig      |   7 ++
> >  drivers/gpio/Makefile     |   2 +-
> >  drivers/gpio/pic32_gpio.c | 175
> > ++++++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 183 insertions(+), 1 deletion(-)
> >  create mode 100644 drivers/gpio/pic32_gpio.c
> > 
> > diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> > index e60e9fd..13e9a6a 100644
> > --- a/drivers/gpio/Kconfig
> > +++ b/drivers/gpio/Kconfig
> > @@ -83,4 +83,11 @@ config VYBRID_GPIO
> >  	help
> >  	  Say yes here to support Vybrid vf610 GPIOs.
> >  
> > +config PIC32_GPIO
> > +	bool "Microchip PIC32 GPIO driver"
> > +	depends on DM_GPIO
> > +	default y if MACH_PIC32

this should be

depends on DM_GPIO && MACH_PIC32

> > +	help
> > +	  Say yes here to support Microchip PIC32 GPIOs.
> > +
> >  endmenu
> > diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> > index fb4fd25..845a6d4 100644
> > --- a/drivers/gpio/Makefile
> > +++ b/drivers/gpio/Makefile
> > @@ -46,4 +46,4 @@ obj-$(CONFIG_STM32_GPIO)	+= stm32_gpio.o
> >  obj-$(CONFIG_ZYNQ_GPIO)		+= zynq_gpio.o
> >  obj-$(CONFIG_VYBRID_GPIO)	+= vybrid_gpio.o
> >  obj-$(CONFIG_HIKEY_GPIO)	+= hi6220_gpio.o
> > -
> > +obj-$(CONFIG_PIC32_GPIO)	+= pic32_gpio.o
> > diff --git a/drivers/gpio/pic32_gpio.c b/drivers/gpio/pic32_gpio.c
> > new file mode 100644
> > index 0000000..5b23af4
> > --- /dev/null
> > +++ b/drivers/gpio/pic32_gpio.c
> > @@ -0,0 +1,175 @@
> > +/*
> > + * Copyright (c) 2015 Microchip Technology Inc
> > + * Purna Chandra Mandal <purna.mandal@microchip.com>
> > + *
> > + * SPDX-License-Identifier:	GPL-2.0+
> > + */
> > +
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <errno.h>
> > +#include <malloc.h>
> > +#include <asm/io.h>
> > +#include <asm/gpio.h>
> > +#include <linux/compat.h>
> > +#include <dt-bindings/gpio/gpio.h>
> > +#include <mach/pic32.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +/* Peripheral Pin Control */
> > +struct pic32_reg_port {
> > +	struct pic32_reg_atomic ansel;
> > +	struct pic32_reg_atomic tris;
> > +	struct pic32_reg_atomic port;
> > +	struct pic32_reg_atomic lat;
> > +	struct pic32_reg_atomic open_drain;
> > +	struct pic32_reg_atomic cnpu;
> > +	struct pic32_reg_atomic cnpd;
> > +	struct pic32_reg_atomic cncon;
> > +};
> > +
> > +enum {
> > +	MICROCHIP_GPIO_DIR_OUT,
> > +	MICROCHIP_GPIO_DIR_IN,
> > +	MICROCHIP_GPIOS_PER_BANK = 16,
> > +};
> > +
> > +struct pic32_gpio_priv {
> > +	struct pic32_reg_port *regs;
> > +	char name[2];
> > +};
> > +
> > +static int pic32_gpio_get_value(struct udevice *dev, unsigned
> > offset)
> > +{
> > +	struct pic32_gpio_priv *priv = dev_get_priv(dev);
> > +
> > +	return !!(readl(&priv->regs->port.raw) & BIT(offset));
> > +}
> > +
> > +static int pic32_gpio_set_value(struct udevice *dev, unsigned
> > offset,
> > +				int value)
> > +{
> > +	struct pic32_gpio_priv *priv = dev_get_priv(dev);
> > +	int mask = BIT(offset);
> > +
> > +	if (value)
> > +		writel(mask, &priv->regs->port.set);
> > +	else
> > +		writel(mask, &priv->regs->port.clr);
> > +
> > +	return 0;
> > +}
> > +
> > +static int pic32_gpio_direction(struct udevice *dev, unsigned
> > offset)
> > +{
> > +	struct pic32_gpio_priv *priv = dev_get_priv(dev);
> > +
> > +	if (readl(&priv->regs->ansel.raw) & BIT(offset))
> > +		return -1;
> > +
> > +	if (readl(&priv->regs->tris.raw) & BIT(offset))
> > +		return MICROCHIP_GPIO_DIR_IN;
> > +	else
> > +		return MICROCHIP_GPIO_DIR_OUT;
> > +}
> > +
> > +static int pic32_gpio_direction_input(struct udevice *dev,
> > unsigned
> > offset)
> > +{
> > +	struct pic32_gpio_priv *priv = dev_get_priv(dev);
> > +	int mask = BIT(offset);
> > +
> > +	writel(mask, &priv->regs->ansel.clr);
> > +	writel(mask, &priv->regs->tris.set);
> > +
> > +	return 0;
> > +}
> > +
> > +static int pic32_gpio_direction_output(struct udevice *dev,
> > +				       unsigned offset, int value)
> > +{
> > +	struct pic32_gpio_priv *priv = dev_get_priv(dev);
> > +	int mask = BIT(offset);
> > +
> > +	writel(mask, &priv->regs->ansel.clr);
> > +	writel(mask, &priv->regs->tris.clr);
> > +
> > +	pic32_gpio_set_value(dev, offset, value);
> > +	return 0;
> > +}
> > +
> > +static int pic32_gpio_xlate(struct udevice *dev, struct gpio_desc
> > *desc,
> > +			    struct fdtdec_phandle_args *args)
> > +{
> > +	desc->offset = args->args[0];
> > +	desc->flags = args->args[1] & GPIO_ACTIVE_LOW ?
> > GPIOD_ACTIVE_LOW : 0;
> > +
> > +	return 0;
> > +}
> > +
> > +static int pic32_gpio_get_function(struct udevice *dev, unsigned
> > offset)
> > +{
> > +	int ret = GPIOF_UNUSED;
> > +
> > +	switch (pic32_gpio_direction(dev, offset)) {
> > +	case MICROCHIP_GPIO_DIR_OUT:
> > +		ret = GPIOF_OUTPUT;
> > +		break;
> > +	case MICROCHIP_GPIO_DIR_IN:
> > +		ret = GPIOF_INPUT;
> > +		break;
> > +	default:
> > +		ret = GPIOF_UNUSED;
> > +		break;
> > +	}
> > +	return ret;
> > +}
> > +
> > +static const struct dm_gpio_ops gpio_pic32_ops = {
> > +	.direction_input	= pic32_gpio_direction_input,
> > +	.direction_output	= pic32_gpio_direction_output,
> > +	.get_value		= pic32_gpio_get_value,
> > +	.set_value		= pic32_gpio_set_value,
> > +	.get_function		= pic32_gpio_get_function,
> > +	.xlate			= pic32_gpio_xlate,
> > +};
> > +
> > +static int pic32_gpio_probe(struct udevice *dev)
> > +{
> > +	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
> > +	struct pic32_gpio_priv *priv = dev_get_priv(dev);
> > +	fdt_addr_t addr;
> > +	fdt_size_t size;
> > +	char *end;
> > +	int bank;
> > +
> > +	addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset,
> > "reg", &size);
> > +	if (addr == FDT_ADDR_T_NONE)
> > +		return -EINVAL;
> > +
> > +	priv->regs = ioremap(addr, size);
> > +	if (!priv->regs)
> > +		return -EINVAL;
> 
> you can drop this check. ioremap() always returns a mapped address.
> 
> > +
> > +	uc_priv->gpio_count = MICROCHIP_GPIOS_PER_BANK;
> > +	end = strrchr(dev->name, '@');
> > +	bank = trailing_strtoln(dev->name, end);
> > +	priv->name[0] = 'A' + bank;
> > +	uc_priv->bank_name = priv->name;
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct udevice_id pic32_gpio_ids[] = {
> > +	{ .compatible = "microchip,pic32mzda-gpio" },
> > +	{ }
> > +};
> > +
> > +U_BOOT_DRIVER(gpio_pic32) = {
> > +	.name		= "gpio_pic32",
> > +	.id		= UCLASS_GPIO,
> > +	.of_match	= pic32_gpio_ids,
> > +	.ops		= &gpio_pic32_ops,
> > +	.probe		= pic32_gpio_probe,
> > +	.priv_auto_alloc_size	= sizeof(struct
> > pic32_gpio_priv),
> > +};
-- 
- Daniel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 08/14] MIPS: Add support for Microchip PIC32MZ[DA] SoC family.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 08/14] MIPS: Add support for Microchip PIC32MZ[DA] SoC family Purna Chandra Mandal
@ 2016-01-13 14:49   ` Daniel Schwierzeck
  2016-01-14  5:54     ` Purna Chandra Mandal
  0 siblings, 1 reply; 62+ messages in thread
From: Daniel Schwierzeck @ 2016-01-13 14:49 UTC (permalink / raw)
  To: u-boot

Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra Mandal:
> Add Microchip PIC32MZ[DA] SoC family support.
> 
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> 
> ---
> 
> Changes in v3:
> - drop forcing CONFIG_MIPS_BOOT_* selection in mach-pic32/Kconfig
> - indent assembly instructions in delay slot
> - made GPIO-nodes child of pinctrl-node in devicetree
> - replace pic32_ioremap() with ioremap()
> 
> Changes in v2:
> - drop board_early_init_f
> - use macro LEAF(), END() for lowlevel_init assembly
> - move initialization of board_init_f() argument to common start.S
> - move initdram() from board/microchip/ to mach-pic32/cpu.c
> - remove MIPS virtual address in favor physical one in dts file
> 
>  arch/mips/dts/pic32mzda.dtsi              | 153
> ++++++++++++++++++++++++++++++
>  arch/mips/mach-pic32/Kconfig              |  20 +++-
>  arch/mips/mach-pic32/Makefile             |   2 +-
>  arch/mips/mach-pic32/cpu.c                | 147
> ++++++++++++++++++++++++++++
>  arch/mips/mach-pic32/include/mach/pic32.h |   3 +
>  arch/mips/mach-pic32/lowlevel_init.S      |  27 ++++++
>  arch/mips/mach-pic32/reset.c              |  36 +++++++
>  7 files changed, 386 insertions(+), 2 deletions(-)
>  create mode 100644 arch/mips/dts/pic32mzda.dtsi
>  create mode 100644 arch/mips/mach-pic32/lowlevel_init.S
>  create mode 100644 arch/mips/mach-pic32/reset.c
> 
> diff --git a/arch/mips/dts/pic32mzda.dtsi
> b/arch/mips/dts/pic32mzda.dtsi
> new file mode 100644
> index 0000000..fe8b13a
> --- /dev/null
> +++ b/arch/mips/dts/pic32mzda.dtsi
> @@ -0,0 +1,153 @@
> +/*
> + * Copyright 2015 Microchip Technology, Inc.
> + * Purna Chandra Mandal, <purna.mandal@microchip.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <dt-bindings/interrupt-controller/irq.h>
> +#include <dt-bindings/clock/microchip,clock.h>
> +#include <dt-bindings/gpio/gpio.h>
> +#include "skeleton.dtsi"
> +
> +/ {
> +	compatible = "microchip,pic32mzda", "microchip,pic32mz";
> +
> +	aliases {
> +		gpio0 = &gpioA;
> +		gpio1 = &gpioB;
> +		gpio2 = &gpioC;
> +		gpio3 = &gpioD;
> +		gpio4 = &gpioE;
> +		gpio5 = &gpioF;
> +		gpio6 = &gpioG;
> +		gpio7 = &gpioH;
> +		gpio8 = &gpioJ;
> +		gpio9 = &gpioK;
> +	};
> +
> +	cpus {
> +		cpu at 0 {
> +			compatible = "mips,mips14kc";
> +		};
> +	};
> +
> +	clock: clk at 1f801200 {
> +		compatible = "microchip,pic32mzda_clk";
> +		reg = <0x1f801200 0x1000>;
> +		clock-cells = <1>;
> +	};
> +
> +	uart1: serial at 1f822000 {
> +		compatible = "microchip,pic32mzda-uart";
> +		reg = <0x1f822000 0x50>;
> +		interrupts = <112 IRQ_TYPE_LEVEL_HIGH>;
> +		status = "disabled";
> +		clocks = <&clock PB2CLK>;
> +	};
> +
> +	uart2: serial at 1f822200 {
> +		compatible = "microchip,pic32mzda-uart";
> +		reg = <0x1f822200 0x50>;
> +		interrupts = <145 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&clock PB2CLK>;
> +		status = "disabled";
> +	};
> +
> +	uart6: serial at 1f822a00 {
> +		compatible = "microchip,pic32mzda-uart";
> +		reg = <0x1f822a00 0x50>;
> +		interrupts = <188 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&clock PB2CLK>;
> +		status = "disabled";
> +	};
> +
> +	evic: interrupt-controller at 1f810000 {
> +		compatible = "microchip,pic32mzda-evic";
> +		interrupt-controller;
> +		#interrupt-cells = <2>;
> +		reg = <0x1f810000 0x1000>;
> +	};
> +
> +	pinctrl: pinctrl at 1f801400 {
> +		compatible = "microchip,pic32mzda-pinctrl";
> +		reg = <0x1f801400 0x100>, /* in  */
> +		      <0x1f801500 0x200>, /* out */
> +		      <0x1f860000 0xa00>; /* port */
> +		reg-names = "ppsin","ppsout","port";
> +		status = "disabled";
> +
> +		ranges = <0 0x1f860000 0xa00>;
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		gpioA: gpio0 at 0 {
> +			compatible = "microchip,pic32mzda-gpio";
> +			reg = <0x000 0x48>;
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +		};
> +
> +		gpioB: gpio1 at 100 {
> +			compatible = "microchip,pic32mzda-gpio";
> +			reg = <0x100 0x48>;
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +		};
> +
> +		gpioC: gpio2 at 200 {
> +			compatible = "microchip,pic32mzda-gpio";
> +			reg = <0x200 0x48>;
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +		};
> +
> +		gpioD: gpio3 at 300 {
> +			compatible = "microchip,pic32mzda-gpio";
> +			reg = <0x300 0x48>;
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +		};
> +
> +		gpioE: gpio4 at 400 {
> +			compatible = "microchip,pic32mzda-gpio";
> +			reg = <0x400 0x48>;
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +		};
> +
> +		gpioF: gpio5 at 500 {
> +			compatible = "microchip,pic32mzda-gpio";
> +			reg = <0x500 0x48>;
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +		};
> +
> +		gpioG: gpio6 at 600 {
> +			compatible = "microchip,pic32mzda-gpio";
> +			reg = <0x600 0x48>;
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +		};
> +
> +		gpioH: gpio7 at 700 {
> +			compatible = "microchip,pic32mzda-gpio";
> +			reg = <0x700 0x48>;
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +		};
> +
> +		gpioJ: gpio8 at 800 {
> +			compatible = "microchip,pic32mzda-gpio";
> +			reg = <0x800 0x48>;
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +		};
> +
> +		gpioK: gpio9 at 900 {
> +			compatible = "microchip,pic32mzda-gpio";
> +			reg = <0x900 0x48>;
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +		};
> +	};
> +};
> diff --git a/arch/mips/mach-pic32/Kconfig b/arch/mips/mach
> -pic32/Kconfig
> index c1cc5e3..74be9fb 100644
> --- a/arch/mips/mach-pic32/Kconfig
> +++ b/arch/mips/mach-pic32/Kconfig
> @@ -2,6 +2,24 @@ menu "Microchip PIC32 platforms"
>  	depends on MACH_PIC32
>  
>  config SYS_SOC
> -	default "none"
> +	default "pic32mzda" if SOC_PIC32MZDA
> +
> +choice
> +	prompt "PIC32 SoC select"
> +
> +config SOC_PIC32MZDA
> +	bool "Microchip PIC32MZ[DA] family"
> +	select SUPPORTS_LITTLE_ENDIAN
> +	select SUPPORTS_CPU_MIPS32_R1
> +	select SUPPORTS_CPU_MIPS32_R2
> +	select MIPS_L1_CACHE_SHIFT_4
> +	select SYS_MIPS_CACHE_INIT_RAM_LOAD

> +	select DM_SERIAL
> +	select PIC32_SERIAL
> +	select PIC32_PINCTRL

I think it is better to remove these three options and to select them
in your board's defconfig. All drivers should have a "depends on
MACH_PIC32 && DM_XYZ". You could add a "default y" to a driver, if that
driver is always needed (e.g. serial, gpio, pinctrl, clk). 

> +	help
> +	  This supports Microchip PIC32MZ[DA] family of
> microcontrollers.
> +
> +endchoice
>  
>  endmenu
> diff --git a/arch/mips/mach-pic32/Makefile b/arch/mips/mach
> -pic32/Makefile
> index cb42607..e321e65 100644
> --- a/arch/mips/mach-pic32/Makefile
> +++ b/arch/mips/mach-pic32/Makefile
> @@ -4,4 +4,4 @@
>  # SPDX-License-Identifier:      GPL-2.0+
>  #
>  
> -obj-y = cpu.o
> +obj-y = cpu.o lowlevel_init.o reset.o
> \ No newline at end of file
> diff --git a/arch/mips/mach-pic32/cpu.c b/arch/mips/mach-pic32/cpu.c
> index 58fd3ab..8ecdef8 100644
> --- a/arch/mips/mach-pic32/cpu.c
> +++ b/arch/mips/mach-pic32/cpu.c
> @@ -6,8 +6,155 @@
>   *
>   */
>  #include <common.h>
> +#include <dm.h>
> +#include <clk.h>
> +#include <debug_uart.h>
> +#include <linux/compiler.h>
> +#include <asm/io.h>
> +#include <asm/mipsregs.h>
> +#include <mach/pic32.h>
> +#include <mach/ddr.h>
> +#include <dt-bindings/clock/microchip,clock.h>
>  
> +/* Flash prefetch */
> +#define PRECON          0x00
> +
> +/* Flash ECCCON */
> +#define ECC_MASK	0x03
> +#define ECC_SHIFT	4
> +
> +#define CLK_MHZ(x)	((x) / 1000000)
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static ulong clk_get_cpu_rate(void)
> +{
> +	int ret;
> +	struct udevice *dev;
> +
> +	ret = uclass_get_device(UCLASS_CLK, 0, &dev);
> +	if (ret) {
> +		panic("uclass-clk: device not found\n");
> +		return 0;
> +	}
> +
> +	return clk_get_rate(dev);
> +}
> +
> +/* initialize prefetch module related to cpu_clk */
> +static void prefetch_init(void)
> +{
> +	struct pic32_reg_atomic *regs;
> +	const void __iomem *base;
> +	int v, nr_waits;
> +	ulong rate;
> +
> +	/* cpu frequency in MHZ */
> +	rate = clk_get_cpu_rate() / 1000000;
> +
> +	/* get flash ECC type */
> +	base = pic32_get_syscfg_base();
> +	v = (readl(base + CFGCON) >> ECC_SHIFT) & ECC_MASK;
> +
> +	if (v < 2) {
> +		if (rate < 66)
> +			nr_waits = 0;
> +		else if (rate < 133)
> +			nr_waits = 1;
> +		else
> +			nr_waits = 2;
> +	} else {
> +		if (rate <= 83)
> +			nr_waits = 0;
> +		else if (rate <= 166)
> +			nr_waits = 1;
> +		else
> +			nr_waits = 2;
> +	}
> +
> +	regs = ioremap(PREFETCH_BASE + PRECON, sizeof(*regs));
> +	writel(nr_waits, &regs->raw);
> +
> +	/* Enable prefetch for all */
> +	writel(0x30, &regs->set);
> +	iounmap(regs);
> +}
> +
> +/* arch specific CPU init after DM */
> +int arch_cpu_init_dm(void)
> +{
> +	/* flash prefetch */
> +	prefetch_init();
> +	return 0;
> +}
> +
> +/* Un-gate DDR2 modules (gated by default) */
> +static void ddr2_pmd_ungate(void)
> +{
> +	void __iomem *regs;
> +
> +	regs = pic32_get_syscfg_base();
> +	writel(0, regs + PMD7);
> +}
> +
> +/* initialize the DDR2 Controller and DDR2 PHY */
>  phys_size_t initdram(int board_type)
>  {
> +	ddr2_pmd_ungate();
> +	ddr2_phy_init();
> +	ddr2_ctrl_init();
> +	return ddr2_calculate_size();
> +}
> +
> +int misc_init_r(void)
> +{
> +	set_io_port_base(0);
> +	return 0;
> +}
> +
> +#ifdef CONFIG_DISPLAY_BOARDINFO
> +const char *get_core_name(void)
> +{
> +	u32 proc_id;
> +	const char *str;
> +
> +	proc_id = read_c0_prid();
> +	switch (proc_id) {
> +	case 0x19e28:
> +		str = "PIC32MZ[DA]";
> +		break;
> +	default:
> +		str = "UNKNOWN";
> +	}
> +
> +	return str;
> +}
> +#endif
> +#ifdef CONFIG_CMD_CLK
> +int soc_clk_dump(void)
> +{
> +	int i, ret;
> +	struct udevice *dev;
> +
> +	ret = uclass_get_device(UCLASS_CLK, 0, &dev);
> +	if (ret) {
> +		printf("clk-uclass not found\n");
> +		return ret;
> +	}
> +
> +	printf("PLL Speed: %lu MHz\n",
> +	       CLK_MHZ(clk_get_periph_rate(dev, PLLCLK)));
> +	printf("CPU Speed: %lu MHz\n", CLK_MHZ(clk_get_rate(dev)));
> +	printf("MPLL Speed: %lu MHz\n",
> +	       CLK_MHZ(clk_get_periph_rate(dev, MPLL)));
> +
> +	for (i = PB1CLK; i <= PB7CLK; i++)
> +		printf("PB%d Clock Speed: %lu MHz\n", i - PB1CLK +
> 1,
> +		       CLK_MHZ(clk_get_periph_rate(dev, i)));
> +
> +	for (i = REF1CLK; i <= REF5CLK; i++)
> +		printf("REFO%d Clock Speed: %lu MHz\n", i - REF1CLK
> + 1,
> +		       CLK_MHZ(clk_get_periph_rate(dev, i)));
>  	return 0;
>  }
> +#endif
> diff --git a/arch/mips/mach-pic32/include/mach/pic32.h
> b/arch/mips/mach-pic32/include/mach/pic32.h
> index 7e41810..16bfacf 100644
> --- a/arch/mips/mach-pic32/include/mach/pic32.h
> +++ b/arch/mips/mach-pic32/include/mach/pic32.h
> @@ -73,4 +73,7 @@ static inline void __iomem
> *pic32_get_syscfg_base(void)
>  	return (void __iomem *)CKSEG1ADDR(PIC32_CFG_BASE);
>  }
>  
> +/* Core */
> +const char *get_core_name(void);
> +
>  #endif	/* __PIC32_REGS_H__ */
> diff --git a/arch/mips/mach-pic32/lowlevel_init.S b/arch/mips/mach
> -pic32/lowlevel_init.S
> new file mode 100644
> index 0000000..e37bebb
> --- /dev/null
> +++ b/arch/mips/mach-pic32/lowlevel_init.S
> @@ -0,0 +1,27 @@
> +/*
> + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + *
> +*/
> +
> +#include <config.h>
> +#include <asm/regdef.h>
> +#include <asm/mipsregs.h>
> +#include <asm/asm.h>
> +
> +LEAF(lowlevel_init)
> +	/*
> +	 * Establish Cause
> +	 * (set IV bit)
> +	 */
> +	li	t1, 0x00800000
> +	mtc0	t1, CP0_CAUSE
> +
> +	/* Establish Wired (and Random) */
> +	mtc0	zero, CP0_WIRED
> +	 nop
> +
> +	jr	ra
> +	 nop
> +	END(lowlevel_init)
> diff --git a/arch/mips/mach-pic32/reset.c b/arch/mips/mach
> -pic32/reset.c
> new file mode 100644
> index 0000000..66c6833
> --- /dev/null
> +++ b/arch/mips/mach-pic32/reset.c
> @@ -0,0 +1,36 @@
> +/*
> + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + *
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <mach/pic32.h>
> +
> +/* SYSKEY */
> +#define UNLOCK_KEY1	0xaa996655
> +#define UNLOCK_KEY2	0x556699aa
> +#define LOCK_KEY	0
> +
> +#define RSWRST          0x1250
> +
> +void _machine_restart(void)
> +{
> +	void __iomem *base;
> +
> +	base = pic32_get_syscfg_base();
> +
> +	/* unlock sequence */
> +	writel(LOCK_KEY, base + SYSKEY);
> +	writel(UNLOCK_KEY1, base + SYSKEY);
> +	writel(UNLOCK_KEY2, base + SYSKEY);
> +
> +	/* soft reset */
> +	writel(0x1, base + RSWRST);
> +	(void) readl(base + RSWRST);
> +
> +	while (1)
> +		;
> +}
-- 
- Daniel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 03/14] drivers: clk: Add clock driver for Microchip PIC32 Microcontroller.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 03/14] drivers: clk: Add clock driver for Microchip PIC32 Microcontroller Purna Chandra Mandal
  2016-01-13 13:38   ` Daniel Schwierzeck
@ 2016-01-13 14:55   ` Tom Rini
  2016-01-14  6:04     ` Purna Chandra Mandal
  1 sibling, 1 reply; 62+ messages in thread
From: Tom Rini @ 2016-01-13 14:55 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 12, 2016 at 03:48:18PM +0530, Purna Chandra Mandal wrote:

> PIC32 clock module consists of multiple oscillators, PLLs, mutiplexers
> and dividers capable of supplying clock to various controllers
> on or off-chip.
[snip]
>  include/dt-bindings/clock/microchip,clock.h        |  29 ++

Has this been submitted for the kernel and reviewed there as well
already?  Thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160113/a617d6b4/attachment.sig>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 04/14] drivers: pinctrl: Add pinctrl driver for Microchip PIC32.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 04/14] drivers: pinctrl: Add pinctrl driver for Microchip PIC32 Purna Chandra Mandal
  2016-01-13 13:42   ` Daniel Schwierzeck
@ 2016-01-13 14:55   ` Tom Rini
  2016-01-13 20:10   ` Simon Glass
  2 siblings, 0 replies; 62+ messages in thread
From: Tom Rini @ 2016-01-13 14:55 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 12, 2016 at 03:48:19PM +0530, Purna Chandra Mandal wrote:

> In PIC32 pin-controller is a combined gpio-controller, pin-mux and
> pin-config module. Remappable peripherals are assigned pins through
> per-pin based muxing logic. And pin configuration are performed on
> specific port registers which are shared along with gpio controller.
> Note, non-remappable peripherals have default pins assigned thus require
> no muxing.
> 
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> 
> 

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160113/b96b174f/attachment.sig>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 07/14] drivers: ddr: Add DDR2 SDRAM controller driver for Microchip PIC32.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 07/14] drivers: ddr: Add DDR2 SDRAM controller driver for Microchip PIC32 Purna Chandra Mandal
  2016-01-13 13:53   ` Daniel Schwierzeck
@ 2016-01-13 14:55   ` Tom Rini
  2016-01-13 20:09   ` Simon Glass
  2 siblings, 0 replies; 62+ messages in thread
From: Tom Rini @ 2016-01-13 14:55 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 12, 2016 at 03:48:22PM +0530, Purna Chandra Mandal wrote:

> This driver initializes PIC32 DDR2 SDRAM controller and internal DDR2 Phy module.
> DDR2 controller operates in half-rate mode (upto 533MHZ frequency).
> 
> Signed-off-by: Paul Thacker <paul.thacker@microchip.com>
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> 
> 

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160113/1fa439b0/attachment.sig>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 06/14] drivers: serial: add driver for Microchip PIC32 UART controller.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 06/14] drivers: serial: add driver for Microchip PIC32 UART controller Purna Chandra Mandal
  2016-01-13 13:49   ` Daniel Schwierzeck
@ 2016-01-13 14:55   ` Tom Rini
  2016-01-13 20:09   ` Simon Glass
  2 siblings, 0 replies; 62+ messages in thread
From: Tom Rini @ 2016-01-13 14:55 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 12, 2016 at 03:48:21PM +0530, Purna Chandra Mandal wrote:

> From: Paul Thacker <paul.thacker@microchip.com>
> 
> This adds PIC32 UART controller support based on driver model.
> 
> Signed-off-by: Paul Thacker <paul.thacker@microchip.com>
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> 
> 

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160113/b13f8897/attachment.sig>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 05/14] drivers: gpio: add driver for Microchip PIC32 GPIO controller.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 05/14] drivers: gpio: add driver for Microchip PIC32 GPIO controller Purna Chandra Mandal
  2016-01-13 13:46   ` Daniel Schwierzeck
@ 2016-01-13 14:55   ` Tom Rini
  2016-01-13 20:10   ` Simon Glass
  2 siblings, 0 replies; 62+ messages in thread
From: Tom Rini @ 2016-01-13 14:55 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 12, 2016 at 03:48:20PM +0530, Purna Chandra Mandal wrote:

> In PIC32 GPIO controller is part of PIC32 pin controller.
> PIC32 has ten independently programmable ports and each with multiple pins.
> Each of these pins can be configured and used as GPIO, provided they
> are not in use for other peripherals.
> 
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> 

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160113/a39be874/attachment.sig>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 02/14] MIPS: initial infrastructure for Microchip PIC32 architecture
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 02/14] MIPS: initial infrastructure for Microchip PIC32 architecture Purna Chandra Mandal
  2016-01-12 12:55   ` Daniel Schwierzeck
@ 2016-01-13 14:56   ` Tom Rini
  1 sibling, 0 replies; 62+ messages in thread
From: Tom Rini @ 2016-01-13 14:56 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 12, 2016 at 03:48:17PM +0530, Purna Chandra Mandal wrote:

> Create initial directory, Kconfigs needed for PIC32 architecture
> support. Also add PIC32 specific register definition required for drivers.
> 
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> 

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160113/fe2928fc/attachment.sig>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 09/14] board: Add Microchip PIC32MZ[DA]-Starter-Kit board.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 09/14] board: Add Microchip PIC32MZ[DA]-Starter-Kit board Purna Chandra Mandal
@ 2016-01-13 14:56   ` Tom Rini
  2016-01-14  6:40     ` Purna Chandra Mandal
  2016-01-13 15:03   ` Daniel Schwierzeck
  1 sibling, 1 reply; 62+ messages in thread
From: Tom Rini @ 2016-01-13 14:56 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 12, 2016 at 03:48:24PM +0530, Purna Chandra Mandal wrote:

> This adds support for Microchip PIC32MZ[DA] StarterKit board
> based on a PIC32MZ[DA] family of microcontroller.
> 
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
[snip]
> diff --git a/configs/pic32mzdask_defconfig b/configs/pic32mzdask_defconfig
> new file mode 100644
> index 0000000..3483eb0
> --- /dev/null
> +++ b/configs/pic32mzdask_defconfig
> @@ -0,0 +1,416 @@
> +#
> +# Automatically generated file; DO NOT EDIT.
> +# U-Boot 2016.01-rc3 Configuration

Please use 'make savedefconfig' to generate this file instead, it will
be much smaller (and this is also what you do with the linux kernel).

> +++ b/include/configs/pic32mzdask.h
[snip]
> +#define CONFIG_SYS_BAUDRATE_TABLE	{9600, 19200, 38400, 57600, 115200}

I think you can use the default here.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160113/4f10d548/attachment.sig>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 10/14] drivers: mmc: add driver for Microchip PIC32 SDHCI controller.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 10/14] drivers: mmc: add driver for Microchip PIC32 SDHCI controller Purna Chandra Mandal
@ 2016-01-13 14:56   ` Tom Rini
  2016-01-13 15:15   ` Daniel Schwierzeck
  1 sibling, 0 replies; 62+ messages in thread
From: Tom Rini @ 2016-01-13 14:56 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 12, 2016 at 03:48:25PM +0530, Purna Chandra Mandal wrote:

> From: Andrei Pistirica <andrei.pistirica@microchip.com>
> 
> This driver implements platform specific glue and fixups for
> PIC32 internal SDHCI controller.
> 
> Signed-off-by: Andrei Pistirica <andrei.pistirica@microchip.com>
> Signed-off-by: Sandeep Sheriker Mallikarjun <sandeepsheriker.mallikarjun@microchip.com>
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> 

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160113/cef2be2c/attachment.sig>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 11/14] board: add SDHCI support for PIC32MZDASK board.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 11/14] board: add SDHCI support for PIC32MZDASK board Purna Chandra Mandal
@ 2016-01-13 14:56   ` Tom Rini
  2016-01-14  8:31     ` Purna Chandra Mandal
  0 siblings, 1 reply; 62+ messages in thread
From: Tom Rini @ 2016-01-13 14:56 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 12, 2016 at 03:48:26PM +0530, Purna Chandra Mandal wrote:

> Enable MMC, SDHCI, FAT FS, EXT4 FS support for PIC32MZ[DA] StarterKit.
> Also add custom scripts, rules to boot Linux from microSD card.
> 
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
[snip]
> +#define CONFIG_EXTRA_ENV_SETTINGS				\
> +	"loadaddr="__stringify(CONFIG_SYS_LOAD_ADDR)"\0"	\
> +	"uenvfile=uEnv.txt\0"					\
> +	"uenvaddr="__stringify(CONFIG_SYS_ENV_ADDR)"\0"		\
> +	"scriptfile=boot.scr\0"					\
> +	"ubootfile=u-boot.bin\0"				\
> +	"importbootenv= "					\
> +		"env import -t -r ${uenvaddr} ${filesize};\0"	\
> +								\
> +	"mmcloadenv=fatload mmc 0 ${uenvaddr} ${uenvfile}\0"	\
> +	"mmcloadscr=fatload mmc 0 ${uenvaddr} ${scriptfile}\0"	\
> +	"mmcloadub=fatload mmc 0 ${loadaddr} ${ubootfile}\0"	\
> +								\
> +	"loadbootenv=run mmcloadenv\0"				\
> +	"loadbootscr=run mmcloadscr\0"				\
> +	"bootcmd_root= "					\
> +		"if run loadbootenv; then "			\
> +			"echo Loaded environment ${uenvfile}; "	\
> +			"run importbootenv; "			\
> +		"fi; "						\
> +		"if test -n \"${bootcmd_uenv}\" ; then "	\
> +			"echo Running bootcmd_uenv ...; "	\
> +			"run bootcmd_uenv; "			\
> +		"fi; "						\
> +		"if run loadbootscr; then "			\
> +			"echo Jumping to ${scriptfile}; "	\
> +			"source ${uenvaddr}; "			\
> +		"fi; "						\
> +		"echo Custom environment or script not found. "	\
> +			"Aborting auto booting...; \0"		\
> +	""
> +
> +#define CONFIG_BOOTCOMMAND		"run bootcmd_root"

I would like to see the env above done as a separate commit and then
using config_distro_default / bootcmd :)

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160113/861e8166/attachment.sig>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 12/14] drivers: net: phy: add SMSC LAN8740 Phy support.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 12/14] drivers: net: phy: add SMSC LAN8740 Phy support Purna Chandra Mandal
@ 2016-01-13 14:56   ` Tom Rini
  2016-01-13 15:19   ` Daniel Schwierzeck
  1 sibling, 0 replies; 62+ messages in thread
From: Tom Rini @ 2016-01-13 14:56 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 12, 2016 at 03:48:27PM +0530, Purna Chandra Mandal wrote:

> Add SMSC LAN8740 Phy support required for PIC32MZDA devices.
> 
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> 

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160113/df77b402/attachment.sig>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 13/14] drivers: net: Add ethernet driver for Microchip PIC32.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 13/14] drivers: net: Add ethernet driver for Microchip PIC32 Purna Chandra Mandal
@ 2016-01-13 14:56   ` Tom Rini
  2016-01-14 10:29     ` Purna Chandra Mandal
  2016-01-13 15:37   ` Daniel Schwierzeck
  1 sibling, 1 reply; 62+ messages in thread
From: Tom Rini @ 2016-01-13 14:56 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 12, 2016 at 03:48:28PM +0530, Purna Chandra Mandal wrote:

> This driver implements MAC and MII layer of the ethernet controller.
> Network data transfer is handled by controller internal DMA engine.
> Ethernet controller is configurable through device-tree file.
> 
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
[snip]
> +/* cache operation helper */
> +#define __dcache_flush(__a, __l) \
> +	flush_dcache_range((ulong)(__a),  ((__l) + (ulong)(__a)))
> +
> +#define __dcache_invalidate(__a, __l) \
> +	invalidate_dcache_range((ulong)(__a),  ((__l) + (ulong)(__a)))

Why using these helper functions instead of directly?  Yes, we may be
casting in some cases and if that's how it must be, so be it (it's how
we're doing it in other drivers).  Thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160113/34495cac/attachment.sig>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 14/14] board: Enable ethernet, tftpboot support to pic32mzdask board.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 14/14] board: Enable ethernet, tftpboot support to pic32mzdask board Purna Chandra Mandal
@ 2016-01-13 14:56   ` Tom Rini
  0 siblings, 0 replies; 62+ messages in thread
From: Tom Rini @ 2016-01-13 14:56 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 12, 2016 at 03:48:29PM +0530, Purna Chandra Mandal wrote:

> This adds ethernet, TFTP support for PIC32MZ[DA] Starter Kit. Also
> custom environment variables/scripts are added to help boot from network.
> 
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> 

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160113/dcf88a81/attachment.sig>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 09/14] board: Add Microchip PIC32MZ[DA]-Starter-Kit board.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 09/14] board: Add Microchip PIC32MZ[DA]-Starter-Kit board Purna Chandra Mandal
  2016-01-13 14:56   ` Tom Rini
@ 2016-01-13 15:03   ` Daniel Schwierzeck
  2016-01-14  8:40     ` Purna Chandra Mandal
  1 sibling, 1 reply; 62+ messages in thread
From: Daniel Schwierzeck @ 2016-01-13 15:03 UTC (permalink / raw)
  To: u-boot

Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra Mandal:
> This adds support for Microchip PIC32MZ[DA] StarterKit board
> based on a PIC32MZ[DA] family of microcontroller.
> 
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> 
> 
> ---
> 
> Changes in v3:
> - drop SKIP_LOWLEVEL_INIT, GBL_DATA_OFFSET from config header
> - move CMD_MEMTEST, CMD_MEMINFO to defconfig
> - increase SYS_MALLOC_F_LEN to 0x600
> - use auto-generated defconfig - no hand edit
> 
> Changes in v2:
> - move CONFIG_SYS_TEXT_BASE (from board/*/config.mk) to
> include/configs/<board>.h
> 
>  arch/mips/dts/Makefile                |   2 +-
>  arch/mips/dts/pic32mzda_sk.dts        |  38 ++++
>  arch/mips/mach-pic32/Kconfig          |  13 ++
>  board/microchip/pic32mzda/Kconfig     |  13 ++
>  board/microchip/pic32mzda/MAINTAINERS |   6 +
>  board/microchip/pic32mzda/Makefile    |   7 +
>  board/microchip/pic32mzda/README      |  22 ++
>  board/microchip/pic32mzda/pic32mzda.c |  31 +++
>  configs/pic32mzdask_defconfig         | 416
> ++++++++++++++++++++++++++++++++++
>  include/configs/pic32mzdask.h         |  94 ++++++++
>  10 files changed, 641 insertions(+), 1 deletion(-)
>  create mode 100644 arch/mips/dts/pic32mzda_sk.dts
>  create mode 100644 board/microchip/pic32mzda/Kconfig
>  create mode 100644 board/microchip/pic32mzda/MAINTAINERS
>  create mode 100644 board/microchip/pic32mzda/Makefile
>  create mode 100644 board/microchip/pic32mzda/README
>  create mode 100644 board/microchip/pic32mzda/pic32mzda.c
>  create mode 100644 configs/pic32mzdask_defconfig
>  create mode 100644 include/configs/pic32mzdask.h
> 
> diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile
> index 47b6eb5..b513918 100644
> --- a/arch/mips/dts/Makefile
> +++ b/arch/mips/dts/Makefile
> @@ -2,7 +2,7 @@
>  # SPDX-License-Identifier:	GPL-2.0+
>  #
>  
> -dtb-y +=
> +dtb-$(CONFIG_TARGET_PIC32MZDASK) += pic32mzda_sk.dtb
>  
>  targets += $(dtb-y)
>  
> diff --git a/arch/mips/dts/pic32mzda_sk.dts
> b/arch/mips/dts/pic32mzda_sk.dts
> new file mode 100644
> index 0000000..99e7f64
> --- /dev/null
> +++ b/arch/mips/dts/pic32mzda_sk.dts
> @@ -0,0 +1,38 @@
> +/*
> + * Copyright (C) 2015 Purna Chandra Mandal, 
> purna.mandal at microchip.com
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +/dts-v1/;
> +
> +#include "pic32mzda.dtsi"
> +
> +/ {
> +	model = "Microchip PIC32MZDASK";
> +	compatible = "microchip,pic32mzdask", "microchip,pic32mzda";
> +
> +	aliases {
> +		console = &uart2;
> +		serial0 = &uart2;
> +	};
> +
> +	chosen {
> +		stdout-path = "serial0:115200n8";
> +	};
> +};
> +
> +&clock {
> +	status = "okay";
> +	u-boot,dm-pre-reloc;
> +};
> +
> +&pinctrl {
> +	status = "okay";
> +	u-boot,dm-pre-reloc;
> +};
> +
> +&uart2 {
> +	status = "okay";
> +	u-boot,dm-pre-reloc;
> +};
> diff --git a/arch/mips/mach-pic32/Kconfig b/arch/mips/mach
> -pic32/Kconfig
> index 74be9fb..d665f63 100644
> --- a/arch/mips/mach-pic32/Kconfig
> +++ b/arch/mips/mach-pic32/Kconfig
> @@ -22,4 +22,17 @@ config SOC_PIC32MZDA
>  
>  endchoice
>  
> +choice
> +	prompt "Board select"
> +
> +config TARGET_PIC32MZDASK
> +	bool "Microchip PIC32MZ[DA] Starter Kit"
> +	depends on SOC_PIC32MZDA
> +	help
> +	  This supports Microchip PIC32MZ[DA] Starter Kit.
> +
> +endchoice
> +
> +source "board/microchip/pic32mzda/Kconfig"
> +
>  endmenu
> diff --git a/board/microchip/pic32mzda/Kconfig
> b/board/microchip/pic32mzda/Kconfig
> new file mode 100644
> index 0000000..8acb393
> --- /dev/null
> +++ b/board/microchip/pic32mzda/Kconfig
> @@ -0,0 +1,13 @@
> +
> +if TARGET_PIC32MZDASK
> +
> +config SYS_BOARD
> +	default "pic32mzda"
> +
> +config SYS_VENDOR
> +	default "microchip"
> +
> +config SYS_CONFIG_NAME
> +	default "pic32mzdask"
> +
> +endif
> diff --git a/board/microchip/pic32mzda/MAINTAINERS
> b/board/microchip/pic32mzda/MAINTAINERS
> new file mode 100644
> index 0000000..c934f1a
> --- /dev/null
> +++ b/board/microchip/pic32mzda/MAINTAINERS
> @@ -0,0 +1,6 @@
> +PIC32MZDASK BOARD
> +M:	Purna Chandra Mandal <purna.mandal@microchip.com>
> +S:	Maintained
> +F:	board/microchip/pic32mzda/
> +F:	include/configs/pic32mzdask.h
> +F:	configs/pic32mzdask_defconfig
> diff --git a/board/microchip/pic32mzda/Makefile
> b/board/microchip/pic32mzda/Makefile
> new file mode 100644
> index 0000000..3629530
> --- /dev/null
> +++ b/board/microchip/pic32mzda/Makefile
> @@ -0,0 +1,7 @@
> +#
> +# (C) Copyright 2015
> +# Purna Chandra Mandal, purna.mandal at microchip.com.
> +#
> +# SPDX-License-Identifier:      GPL-2.0+
> +#
> +obj-y := pic32mzda.o
> diff --git a/board/microchip/pic32mzda/README
> b/board/microchip/pic32mzda/README
> new file mode 100644
> index 0000000..91d16ab
> --- /dev/null
> +++ b/board/microchip/pic32mzda/README
> @@ -0,0 +1,22 @@
> +/*
> + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
> + */
> +
> +PIC32MZ[DA] Starter Kit
> +----------------------------------------
> +PIC32MZ[DA] Starter Kit is based on PIC32MZ[DA] family of micro
> -controller.
> +This family is powered by MIPS M14KEC 32bit general purpose core and
> has
> +advanced microcontroller features and peripherals.
> +
> +This processor boots with proprietary stage1 bootloader running from
> internal
> +boot-flash. Stage1 bootloader inturns locates and jumps to U-Boot
> programmed
> +on internal program-flash. Finally U-Boot loads OS image (along with
> other
> +required files for booting) from either uSD card, or ethernet, or
> from USB
> +storage.
> +
> +To boot Linux following three files are mandatory - uEnv.txt (custom
> U-Boot
> +environment file), uImage, *.dtb (platform device-tree-blob file).
> +
> +U-Boot jumps to Linux using UHI specification.
> +
> +Visit http://microchip.com for details.
> diff --git a/board/microchip/pic32mzda/pic32mzda.c
> b/board/microchip/pic32mzda/pic32mzda.c
> new file mode 100644
> index 0000000..afe2ab8
> --- /dev/null
> +++ b/board/microchip/pic32mzda/pic32mzda.c
> @@ -0,0 +1,31 @@
> +/*
> + * Microchip PIC32MZ[DA] Starter Kit board
> + *
> + * Copyright (C) 2015, Microchip Technology Inc.
> + * Purna Chandra Mandal <purna.mandal@microchip.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + *
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <clk.h>
> +#include <mach/pic32.h>
> +
> +#ifdef CONFIG_DISPLAY_BOARDINFO
> +int checkboard(void)
> +{
> +	ulong rate = 0;
> +	struct udevice *dev;
> +
> +	printf("Core: %s\n", get_core_name());
> +
> +	if (!uclass_get_device(UCLASS_CLK, 0, &dev)) {
> +		rate = clk_get_rate(dev);
> +		printf("CPU Speed: %lu MHz\n", rate / 1000000);
> +	}
> +
> +	return 0;
> +}
> +#endif
> diff --git a/configs/pic32mzdask_defconfig
> b/configs/pic32mzdask_defconfig
> new file mode 100644
> index 0000000..3483eb0
> --- /dev/null
> +++ b/configs/pic32mzdask_defconfig
> @@ -0,0 +1,416 @@
> +#
> +# Automatically generated file; DO NOT EDIT.
> +# U-Boot 2016.01-rc3 Configuration
> +#

this is not a defconfig file. Please create it like that (after you
fixed the remaining Kconfig issues in your other patches)

$ make pic32mzdask_defconfig

$ make menuconfig (optionally, if you want to change some options)

$ make savedefconfig
$ cp defconfig configs/pic32mzdask_defconfig

The purpose is, that all options with "default y" or "select XYZ" are
filtered out and that you only store the options different from the
default ones.

With your current configuration, your defconfig file would look like
this:

CONFIG_MIPS=y
CONFIG_SYS_MALLOC_F_LEN=0x600
CONFIG_DM_GPIO=y
CONFIG_MACH_PIC32=y
# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
CONFIG_MIPS_BOOT_FDT=y
CONFIG_DEFAULT_DEVICE_TREE="pic32mzda_sk"
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PROMPT="dask # "
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_SAVEENV is not set
CONFIG_LOOPW=y
CONFIG_CMD_MEMTEST=y
CONFIG_CMD_MEMINFO=y
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_FPGA is not set
CONFIG_CMD_GPIO=y
CONFIG_CMD_RARP=y
CONFIG_CMD_DHCP=y
CONFIG_CMD_PING=y
CONFIG_CMD_TIME=y
CONFIG_OF_EMBED=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_CLK=y
CONFIG_DM_MMC=y
CONFIG_PIC32_SDHCI=y
CONFIG_DM_ETH=y
CONFIG_PHYLIB=y
CONFIG_PIC32_ETH=y
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_FULL is not set
CONFIG_SYS_VSNPRINTF=y
CONFIG_USE_TINY_PRINTF=y
CONFIG_CMD_DHRYSTONE=y



> +CONFIG_HAVE_GENERIC_BOARD=y
> +CONFIG_SYS_GENERIC_BOARD=y
> +# CONFIG_ARC is not set
> +# CONFIG_ARM is not set
> +# CONFIG_AVR32 is not set
> +# CONFIG_BLACKFIN is not set
> +# CONFIG_M68K is not set
> +# CONFIG_MICROBLAZE is not set
> +CONFIG_MIPS=y
> +# CONFIG_NDS32 is not set
> +# CONFIG_NIOS2 is not set
> +# CONFIG_OPENRISC is not set
> +# CONFIG_PPC is not set
> +# CONFIG_SANDBOX is not set
> +# CONFIG_SH is not set
> +# CONFIG_SPARC is not set
> +# CONFIG_X86 is not set
> +CONFIG_SYS_ARCH="mips"
> +CONFIG_SYS_CPU="mips32"
> +CONFIG_SYS_SOC="pic32mzda"
> +CONFIG_SYS_VENDOR="microchip"
> +CONFIG_SYS_BOARD="pic32mzda"
> +CONFIG_SYS_CONFIG_NAME="pic32mzdask"
> +CONFIG_SYS_MALLOC_F_LEN=0x600
> +CONFIG_SYS_MALLOC_F=y
> +CONFIG_DM_SERIAL=y
> +# CONFIG_DM_SPI is not set
> +# CONFIG_DM_I2C is not set
> +CONFIG_DM_GPIO=y
> +
> +#
> +# MIPS architecture
> +#
> +# CONFIG_TARGET_QEMU_MIPS is not set
> +# CONFIG_TARGET_MALTA is not set
> +# CONFIG_TARGET_VCT is not set
> +# CONFIG_TARGET_DBAU1X00 is not set
> +# CONFIG_TARGET_PB1X00 is not set
> +CONFIG_MACH_PIC32=y
> +
> +#
> +# Microchip PIC32 platforms
> +#
> +CONFIG_SOC_PIC32MZDA=y
> +CONFIG_TARGET_PIC32MZDASK=y
> +CONFIG_SYS_LITTLE_ENDIAN=y
> +# CONFIG_CPU_MIPS32_R1 is not set
> +CONFIG_CPU_MIPS32_R2=y
> +
> +#
> +# OS boot interface
> +#
> +CONFIG_MIPS_BOOT_CMDLINE_LEGACY=y
> +# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
> +CONFIG_MIPS_BOOT_FDT=y
> +CONFIG_SUPPORTS_LITTLE_ENDIAN=y
> +CONFIG_SUPPORTS_CPU_MIPS32_R1=y
> +CONFIG_SUPPORTS_CPU_MIPS32_R2=y
> +CONFIG_CPU_MIPS32=y
> +CONFIG_32BIT=y
> +CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD=y
> +CONFIG_MIPS_L1_CACHE_SHIFT_4=y
> +CONFIG_MIPS_L1_CACHE_SHIFT=4
> +# CONFIG_DM_KEYBOARD is not set
> +CONFIG_DEFAULT_DEVICE_TREE="pic32mzda_sk"
> +
> +#
> +# General setup
> +#
> +CONFIG_LOCALVERSION=""
> +CONFIG_LOCALVERSION_AUTO=y
> +CONFIG_CC_OPTIMIZE_FOR_SIZE=y
> +CONFIG_EXPERT=y
> +CONFIG_SYS_MALLOC_CLEAR_ON_INIT=y
> +
> +#
> +# Boot images
> +#
> +# CONFIG_FIT is not set
> +CONFIG_SYS_EXTRA_OPTIONS=""
> +
> +#
> +# Command line interface
> +#
> +CONFIG_HUSH_PARSER=y
> +CONFIG_SYS_HUSH_PARSER=y
> +CONFIG_SYS_PROMPT="dask # "
> +
> +#
> +# Autoboot options
> +#
> +# CONFIG_AUTOBOOT_KEYED is not set
> +
> +#
> +# Commands
> +#
> +
> +#
> +# Info commands
> +#
> +CONFIG_CMD_BDI=y
> +CONFIG_CMD_CONSOLE=y
> +# CONFIG_CMD_CPU is not set
> +# CONFIG_CMD_LICENSE is not set
> +
> +#
> +# Boot commands
> +#
> +CONFIG_CMD_BOOTD=y
> +CONFIG_CMD_BOOTM=y
> +CONFIG_CMD_ELF=y
> +CONFIG_CMD_GO=y
> +CONFIG_CMD_RUN=y
> +CONFIG_CMD_IMI=y
> +# CONFIG_CMD_IMLS is not set
> +CONFIG_CMD_XIMG=y
> +
> +#
> +# Environment commands
> +#
> +# CONFIG_CMD_EXPORTENV is not set
> +CONFIG_CMD_IMPORTENV=y
> +CONFIG_CMD_EDITENV=y
> +# CONFIG_CMD_SAVEENV is not set
> +CONFIG_CMD_ENV_EXISTS=y
> +
> +#
> +# Memory commands
> +#
> +CONFIG_CMD_MEMORY=y
> +CONFIG_CMD_CRC32=y
> +CONFIG_LOOPW=y
> +CONFIG_CMD_MEMTEST=y
> +# CONFIG_CMD_MX_CYCLIC is not set
> +CONFIG_CMD_MEMINFO=y
> +
> +#
> +# Device access commands
> +#
> +CONFIG_CMD_DM=y
> +# CONFIG_CMD_DEMO is not set
> +CONFIG_CMD_LOADB=y
> +CONFIG_CMD_LOADS=y
> +# CONFIG_CMD_FLASH is not set
> +# CONFIG_CMD_NAND is not set
> +# CONFIG_CMD_SF is not set
> +# CONFIG_CMD_SPI is not set
> +# CONFIG_CMD_I2C is not set
> +# CONFIG_CMD_USB is not set
> +# CONFIG_CMD_FPGA is not set
> +CONFIG_CMD_GPIO=y
> +
> +#
> +# Shell scripting commands
> +#
> +CONFIG_CMD_ECHO=y
> +CONFIG_CMD_ITEST=y
> +CONFIG_CMD_SOURCE=y
> +CONFIG_CMD_SETEXPR=y
> +
> +#
> +# Network commands
> +#
> +# CONFIG_CMD_NET is not set
> +# CONFIG_CMD_TFTPPUT is not set
> +# CONFIG_CMD_TFTPSRV is not set
> +# CONFIG_CMD_RARP is not set
> +# CONFIG_CMD_DHCP is not set
> +# CONFIG_CMD_NFS is not set
> +# CONFIG_CMD_PING is not set
> +# CONFIG_CMD_CDP is not set
> +# CONFIG_CMD_SNTP is not set
> +# CONFIG_CMD_DNS is not set
> +# CONFIG_CMD_LINK_LOCAL is not set
> +
> +#
> +# Misc commands
> +#
> +CONFIG_CMD_TIME=y
> +CONFIG_CMD_MISC=y
> +# CONFIG_CMD_TIMER is not set
> +
> +#
> +# Boot timing
> +#
> +# CONFIG_BOOTSTAGE is not set
> +CONFIG_BOOTSTAGE_USER_COUNT=20
> +CONFIG_BOOTSTAGE_STASH_ADDR=0
> +CONFIG_BOOTSTAGE_STASH_SIZE=4096
> +
> +#
> +# Power commands
> +#
> +
> +#
> +# Security commands
> +#
> +# CONFIG_CONSOLE_RECORD is not set
> +CONFIG_SUPPORT_OF_CONTROL=y
> +
> +#
> +# Device Tree Control
> +#
> +CONFIG_OF_CONTROL=y
> +# CONFIG_OF_SEPARATE is not set
> +CONFIG_OF_EMBED=y
> +# CONFIG_NET is not set
> +
> +#
> +# Device Drivers
> +#
> +
> +#
> +# Generic Driver Options
> +#
> +CONFIG_DM=y
> +CONFIG_DM_WARN=y
> +CONFIG_DM_DEVICE_REMOVE=y
> +CONFIG_DM_STDIO=y
> +CONFIG_DM_SEQ_ALIAS=y
> +# CONFIG_REGMAP is not set
> +# CONFIG_SPL_REGMAP is not set
> +# CONFIG_DEVRES is not set
> +CONFIG_SIMPLE_BUS=y
> +CONFIG_OF_TRANSLATE=y
> +# CONFIG_ADC is not set
> +# CONFIG_ADC_EXYNOS is not set
> +# CONFIG_ADC_SANDBOX is not set
> +CONFIG_CLK=y
> +# CONFIG_SPL_CLK is not set
> +# CONFIG_CPU is not set
> +
> +#
> +# Hardware crypto devices
> +#
> +# CONFIG_FSL_CAAM is not set
> +
> +#
> +# Demo for driver model
> +#
> +# CONFIG_DM_DEMO is not set
> +
> +#
> +# DFU support
> +#
> +# CONFIG_DFU_TFTP is not set
> +
> +#
> +# GPIO Support
> +#
> +# CONFIG_ALTERA_PIO is not set
> +# CONFIG_DWAPB_GPIO is not set
> +# CONFIG_ATMEL_PIO4 is not set
> +# CONFIG_LPC32XX_GPIO is not set
> +# CONFIG_ROCKCHIP_GPIO is not set
> +# CONFIG_VYBRID_GPIO is not set
> +CONFIG_PIC32_GPIO=y
> +
> +#
> +# I2C support
> +#
> +# CONFIG_DM_I2C_COMPAT is not set
> +# CONFIG_CROS_EC_KEYB is not set
> +
> +#
> +# LED Support
> +#
> +# CONFIG_LED is not set
> +
> +#
> +# Multifunction device drivers
> +#
> +# CONFIG_MISC is not set
> +# CONFIG_CROS_EC is not set
> +# CONFIG_FSL_SEC_MON is not set
> +# CONFIG_MXC_OCOTP is not set
> +# CONFIG_PCA9551_LED is not set
> +# CONFIG_RESET is not set
> +
> +#
> +# MMC Host controller Support
> +#
> +# CONFIG_DM_MMC is not set
> +
> +#
> +# MTD Support
> +#
> +# CONFIG_MTD is not set
> +
> +#
> +# NAND Device Support
> +#
> +# CONFIG_NAND_DENALI is not set
> +# CONFIG_NAND_VF610_NFC is not set
> +# CONFIG_NAND_PXA3XX is not set
> +
> +#
> +# Generic NAND options
> +#
> +
> +#
> +# SPI Flash Support
> +#
> +# CONFIG_SPI_FLASH is not set
> +# CONFIG_DM_ETH is not set
> +# CONFIG_PHYLIB is not set
> +
> +#
> +# PCI
> +#
> +# CONFIG_DM_PCI is not set
> +
> +#
> +# Pin controllers
> +#
> +CONFIG_PINCTRL=y
> +# CONFIG_PINCTRL_FULL is not set
> +# CONFIG_ROCKCHIP_PINCTRL is not set
> +# CONFIG_ROCKCHIP_3036_PINCTRL is not set
> +CONFIG_PIC32_PINCTRL=y
> +
> +#
> +# Power
> +#
> +# CONFIG_DM_PMIC is not set
> +# CONFIG_DM_REGULATOR is not set
> +# CONFIG_RAM is not set
> +
> +#
> +# Remote Processor drivers
> +#
> +
> +#
> +# Real Time Clock
> +#
> +# CONFIG_DM_RTC is not set
> +
> +#
> +# Serial drivers
> +#
> +CONFIG_REQUIRE_SERIAL_CONSOLE=y
> +# CONFIG_DEBUG_UART is not set
> +# CONFIG_ALTERA_JTAG_UART is not set
> +# CONFIG_ALTERA_UART is not set
> +# CONFIG_SYS_NS16550 is not set
> +CONFIG_PIC32_SERIAL=y
> +
> +#
> +# Sound support
> +#
> +# CONFIG_SOUND is not set
> +
> +#
> +# SPI Support
> +#
> +# CONFIG_FSL_ESPI is not set
> +# CONFIG_TI_QSPI is not set
> +# CONFIG_DM_THERMAL is not set
> +
> +#
> +# Timer Support
> +#
> +# CONFIG_TIMER is not set
> +
> +#
> +# TPM support
> +#
> +# CONFIG_USB is not set
> +
> +#
> +# Graphics support
> +#
> +# CONFIG_VIDEO_VESA is not set
> +# CONFIG_VIDEO_LCD_ANX9804 is not set
> +# CONFIG_VIDEO_LCD_SSD2828 is not set
> +# CONFIG_DISPLAY_PORT is not set
> +# CONFIG_VIDEO_TEGRA124 is not set
> +# CONFIG_VIDEO_BRIDGE is not set
> +# CONFIG_PHYS_TO_BUS is not set
> +
> +#
> +# File systems
> +#
> +
> +#
> +# Library routines
> +#
> +# CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED is not set
> +CONFIG_HAVE_PRIVATE_LIBGCC=y
> +# CONFIG_USE_PRIVATE_LIBGCC is not set
> +CONFIG_SYS_HZ=1000
> +CONFIG_SYS_VSNPRINTF=y
> +CONFIG_USE_TINY_PRINTF=y
> +CONFIG_REGEX=y
> +# CONFIG_LIB_RAND is not set
> +CONFIG_CMD_DHRYSTONE=y
> +# CONFIG_RSA is not set
> +# CONFIG_TPM is not set
> +
> +#
> +# Hashing Support
> +#
> +# CONFIG_SHA1 is not set
> +# CONFIG_SHA256 is not set
> +# CONFIG_SHA_HW_ACCEL is not set
> +
> +#
> +# Compression Support
> +#
> +# CONFIG_LZ4 is not set
> +# CONFIG_ERRNO_STR is not set
> +# CONFIG_UNIT_TEST is not set
> diff --git a/include/configs/pic32mzdask.h
> b/include/configs/pic32mzdask.h
> new file mode 100644
> index 0000000..6552fa2
> --- /dev/null
> +++ b/include/configs/pic32mzdask.h
> @@ -0,0 +1,94 @@
> +/*
> + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + *
> + * Microchip PIC32MZ[DA] Starter Kit.
> + */
> +
> +#ifndef __PIC32MZDASK_CONFIG_H
> +#define __PIC32MZDASK_CONFIG_H
> +
> +/* System Configuration */
> +#define CONFIG_SYS_TEXT_BASE		0x9d004000 /* .text */
> +#define CONFIG_DISPLAY_BOARDINFO
> +
> +/*--------------------------------------------
> + * CPU configuration
> + */
> +/* CPU Timer rate */
> +#define CONFIG_SYS_MIPS_TIMER_FREQ	100000000
> +
> +/* Cache Configuration */
> +#define CONFIG_SYS_MIPS_CACHE_MODE	CONF_CM_CACHABLE_NONCOHERE
> NT
> +
> +/*------------------------------------------------------------------
> ----
> + * Memory Layout
> + */
> +#define CONFIG_SYS_SRAM_BASE		0x80000000
> +#define CONFIG_SYS_SRAM_SIZE		0x00080000 /* 512K */
> +
> +/* Initial RAM for temporary stack, global data */
> +#define CONFIG_SYS_INIT_RAM_SIZE	0x10000
> +#define CONFIG_SYS_INIT_RAM_ADDR	\
> +	(CONFIG_SYS_SRAM_BASE + CONFIG_SYS_SRAM_SIZE -
> CONFIG_SYS_INIT_RAM_SIZE)
> +#define CONFIG_SYS_INIT_SP_ADDR		\
> +	(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE - 1)
> +
> +/* SDRAM Configuration (for final code, data, stack, heap) */
> +#define CONFIG_SYS_SDRAM_BASE		0x88000000
> +#define CONFIG_SYS_MALLOC_LEN		(256 << 10)
> +#define CONFIG_SYS_BOOTPARAMS_LEN	(4 << 10)
> +#define CONFIG_STACKSIZE		(4 << 10) /* regular stack
> */
> +
> +#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE
> +#define CONFIG_SYS_MONITOR_LEN		(192 << 10)
> +
> +#define CONFIG_SYS_LOAD_ADDR		0x88500000 /* default
> load address */
> +#define CONFIG_SYS_ENV_ADDR		0x88300000
> +
> +/* Memory Test */
> +#define CONFIG_SYS_MEMTEST_START	0x88000000
> +#define CONFIG_SYS_MEMTEST_END		0x88080000
> +
> +/*------------------------------------------------------------------
> ----
> + * Commands
> + */
> +#define CONFIG_SYS_LONGHELP		/* undef to save memory
> */
> +#define CONFIG_CMD_CLK
> +
> +/*-------------------------------------------------
> + * FLASH configuration
> + */
> +#define CONFIG_SYS_NO_FLASH
> +
> +/*------------------------------------------------------------
> + * Console Configuration
> + */
> +#define CONFIG_BAUDRATE			115200
> +#define CONFIG_SYS_BAUDRATE_TABLE	{9600, 19200, 38400, 57600,
> 115200}
> +#define CONFIG_SYS_CBSIZE		1024 /* Console I/O Buffer
> Size   */
> +#define CONFIG_SYS_MAXARGS		16   /* max number of
> command args*/
> +#define CONFIG_SYS_PBSIZE		\
> +		(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
> +#define CONFIG_CMDLINE_EDITING		1
> +
> +/*
> + * Handover flattened device tree (dtb file) to Linux kernel
> + */
> +#define CONFIG_OF_LIBFDT	1
> +
> +/* -------------------------------------------------
> + * Environment
> + */
> +#define CONFIG_ENV_IS_NOWHERE	1
> +#define CONFIG_ENV_SIZE		0x4000
> +
> +/* -----------------------------------------------------------------
> ----
> + * Board boot configuration
> + */
> +#define CONFIG_TIMESTAMP	/* Print image info with timestamp
> */
> +#define CONFIG_BOOTDELAY	5 /* autoboot after X seconds     */
> +#undef	CONFIG_BOOTARGS
> +
> +#endif	/* __PIC32MZDASK_CONFIG_H */
-- 
- Daniel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 10/14] drivers: mmc: add driver for Microchip PIC32 SDHCI controller.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 10/14] drivers: mmc: add driver for Microchip PIC32 SDHCI controller Purna Chandra Mandal
  2016-01-13 14:56   ` Tom Rini
@ 2016-01-13 15:15   ` Daniel Schwierzeck
  2016-01-14  9:18     ` Purna Chandra Mandal
  1 sibling, 1 reply; 62+ messages in thread
From: Daniel Schwierzeck @ 2016-01-13 15:15 UTC (permalink / raw)
  To: u-boot

Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra Mandal:
> From: Andrei Pistirica <andrei.pistirica@microchip.com>
> 
> This driver implements platform specific glue and fixups for
> PIC32 internal SDHCI controller.
> 
> Signed-off-by: Andrei Pistirica <andrei.pistirica@microchip.com>
> Signed-off-by: Sandeep Sheriker Mallikarjun <
> sandeepsheriker.mallikarjun at microchip.com>
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> 

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

nits below

> ---
> 
> Changes in v3:
> - remove ofdata_to_platdata, and replace platdata with priv
> - replace pic32_ioremap() with ioremap()
> 
> Changes in v2:
> - drop sdhci shared bus configuration (for shared interrupt, clock
> pins)
> 
>  drivers/mmc/Kconfig       |  6 +++++
>  drivers/mmc/Makefile      |  2 +-
>  drivers/mmc/pic32_sdhci.c | 61
> +++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/mmc/sdhci.c       | 12 ++++++++++
>  4 files changed, 80 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/mmc/pic32_sdhci.c
> 
> diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
> index ceae7bc..0b6f54b 100644
> --- a/drivers/mmc/Kconfig
> +++ b/drivers/mmc/Kconfig
> @@ -31,4 +31,10 @@ config SH_SDHI
>  	help
>  	  Support for the on-chip SDHI host controller on
> SuperH/Renesas ARM SoCs platform
>  
> +config PIC32_SDHCI
> +	bool "Microchip PIC32 on-chip SDHCI support"
> +	depends on DM_MMC && MACH_PIC32
> +	help
> +	  Support for the on-chip SDHCI support on Microchip PIC32
> platforms.
> +
>  endmenu
> diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
> index 5d35705..c9c3e3e 100644
> --- a/drivers/mmc/Makefile
> +++ b/drivers/mmc/Makefile
> @@ -48,4 +48,4 @@ obj-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o
>  else
>  obj-$(CONFIG_GENERIC_MMC) += mmc_write.o
>  endif
> -
> +obj-$(CONFIG_PIC32_SDHCI) += pic32_sdhci.o
> diff --git a/drivers/mmc/pic32_sdhci.c b/drivers/mmc/pic32_sdhci.c
> new file mode 100644
> index 0000000..f8a5a23
> --- /dev/null
> +++ b/drivers/mmc/pic32_sdhci.c
> @@ -0,0 +1,61 @@
> +/*
> + * Support of SDHCI for Microchip PIC32 SoC.
> + *
> + * Copyright (C) 2015 Microchip Technology Inc.
> + * Andrei Pistirica <andrei.pistirica@microchip.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <dm.h>
> +#include <common.h>
> +#include <sdhci.h>
> +#include <asm/errno.h>
> +#include <mach/pic32.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static int pic32_sdhci_probe(struct udevice *dev)
> +{
> +	struct sdhci_host *host = dev_get_priv(dev);
> +	const void *fdt = gd->fdt_blob;
> +	u32 f_min_max[2];
> +	fdt_addr_t addr;
> +	fdt_size_t size;
> +	int ret;
> +
> +	addr = fdtdec_get_addr_size(fdt, dev->of_offset, "reg",
> &size);
> +	if (addr == FDT_ADDR_T_NONE)
> +		return -EINVAL;
> +
> +	host->ioaddr = ioremap(addr, size);
> +	if (!host->ioaddr)
> +		return -EINVAL;

this check can be dropped. ioremap() always returns a mapped address

> +
> +	host->name	= (char *)dev->name;
> +	host->quirks	= SDHCI_QUIRK_NO_HISPD_BIT;
> +	host->bus_width	= fdtdec_get_int(gd->fdt_blob, dev
> ->of_offset,
> +					"bus-width", 4);
> +
> +	ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
> +				   "clock-freq-min-max", f_min_max,
> 2);
> +	if (ret) {
> +		printf("sdhci: clock-freq-min-max not found\n");
> +		return ret;
> +	}
> +
> +	return add_sdhci(host, f_min_max[1], f_min_max[0]);
> +}
> +
> +static const struct udevice_id pic32_sdhci_ids[] = {
> +	{ .compatible = "microchip,pic32mzda-sdhci" },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(pic32_sdhci_drv) = {
> +	.name			= "pic32_sdhci",
> +	.id			= UCLASS_MMC,
> +	.of_match		= pic32_sdhci_ids,
> +	.probe			= pic32_sdhci_probe,
> +	.priv_auto_alloc_size	= sizeof(struct sdhci_host),
> +};
> diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
> index 02d71b9..f32fe67 100644
> --- a/drivers/mmc/sdhci.c
> +++ b/drivers/mmc/sdhci.c
> @@ -424,6 +424,18 @@ static void sdhci_set_ios(struct mmc *mmc)
>  	if (host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)
>  		ctrl &= ~SDHCI_CTRL_HISPD;
>  
> +#if defined(CONFIG_PIC32_SDHCI)
> +	/*
> +	* In PIC32MZ[DA] due to h/w bug SDHCI fails detecting card
> when JTAG
> +	* is not connected.
> +	* To work-around this problem:
> +	*  - set Card_Detect_Signal_Selection bit in
> SDHCI_Host_Control register
> +	*  - clear Card_Detect_Test_Level bit in SDHCI_Host_Control
> register
> +	*/
> +	ctrl |= SDHCI_CTRL_CD_TEST;
> +	ctrl &= ~SDHCI_CTRL_CD_TEST_INS;
> +#endif

I think this could (or should?) be implemented with a new quirks bit

> +
>  	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
>  }
>  
-- 
- Daniel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 12/14] drivers: net: phy: add SMSC LAN8740 Phy support.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 12/14] drivers: net: phy: add SMSC LAN8740 Phy support Purna Chandra Mandal
  2016-01-13 14:56   ` Tom Rini
@ 2016-01-13 15:19   ` Daniel Schwierzeck
  1 sibling, 0 replies; 62+ messages in thread
From: Daniel Schwierzeck @ 2016-01-13 15:19 UTC (permalink / raw)
  To: u-boot

Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra Mandal:
> Add SMSC LAN8740 Phy support required for PIC32MZDA devices.
> 
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

> 
> ---
> 
> Changes in v3: None
> Changes in v2: None
> 
>  drivers/net/phy/smsc.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
> index bfd9815..34986a2 100644
> --- a/drivers/net/phy/smsc.c
> +++ b/drivers/net/phy/smsc.c
> @@ -69,11 +69,21 @@ static struct phy_driver lan8710_driver = {
>  	.shutdown = &genphy_shutdown,
>  };
>  
> +static struct phy_driver lan8740_driver = {
> +	.name = "SMSC LAN8740",
> +	.uid = 0x0007c110,
> +	.mask = 0xffff0,
> +	.features = PHY_BASIC_FEATURES,
> +	.config = &genphy_config_aneg,
> +	.startup = &genphy_startup,
> +	.shutdown = &genphy_shutdown,
> +};
>  int phy_smsc_init(void)
>  {
>  	phy_register(&lan8710_driver);
>  	phy_register(&lan911x_driver);
>  	phy_register(&lan8700_driver);
> +	phy_register(&lan8740_driver);
>  
>  	return 0;
>  }
-- 
- Daniel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 13/14] drivers: net: Add ethernet driver for Microchip PIC32.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 13/14] drivers: net: Add ethernet driver for Microchip PIC32 Purna Chandra Mandal
  2016-01-13 14:56   ` Tom Rini
@ 2016-01-13 15:37   ` Daniel Schwierzeck
  2016-01-14 10:05     ` Purna Chandra Mandal
  1 sibling, 1 reply; 62+ messages in thread
From: Daniel Schwierzeck @ 2016-01-13 15:37 UTC (permalink / raw)
  To: u-boot

Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra Mandal:
> This driver implements MAC and MII layer of the ethernet controller.
> Network data transfer is handled by controller internal DMA engine.
> Ethernet controller is configurable through device-tree file.
> 
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> 
> 
> ---
> 
> Changes in v3:
> - merge wrappers with eth operation callbacks
> - read phy address from device-tree
> - rename functions (e.g. _eth_xyz() with pic32_eth_xyz())
> 
> Changes in v2: None
> 
>  drivers/net/Kconfig      |   7 +
>  drivers/net/Makefile     |   1 +
>  drivers/net/pic32_eth.c  | 606
> +++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/net/pic32_eth.h  | 171 +++++++++++++
>  drivers/net/pic32_mdio.c | 121 ++++++++++
>  5 files changed, 906 insertions(+)
>  create mode 100644 drivers/net/pic32_eth.c
>  create mode 100644 drivers/net/pic32_eth.h
>  create mode 100644 drivers/net/pic32_mdio.c
> 
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index ae5e78d..dc49493 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -108,4 +108,11 @@ config ZYNQ_GEM
>  	help
>  	  This MAC is present in Xilinx Zynq and ZynqMP SoCs.
>  
> +config PIC32_ETH
> +	bool "Microchip PIC32 Ethernet Support"
> +	depends on MACH_PIC32

should be

depends on DM_ETH && MACH_PIC32
select PHYLIB

> +	help
> +	  This driver implements 10/100 Mbps Ethernet and MAC layer
> for
> +	  Microchip PIC32 microcontrollers.
> +
>  endif # NETDEVICES
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 150470c..33a81ee 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -72,3 +72,4 @@ obj-$(CONFIG_FSL_MC_ENET) += fsl-mc/
>  obj-$(CONFIG_FSL_MC_ENET) += ldpaa_eth/
>  obj-$(CONFIG_FSL_MEMAC) += fm/memac_phy.o
>  obj-$(CONFIG_VSC9953) += vsc9953.o
> +obj-$(CONFIG_PIC32_ETH) += pic32_mdio.o pic32_eth.o
> diff --git a/drivers/net/pic32_eth.c b/drivers/net/pic32_eth.c
> new file mode 100644
> index 0000000..1cef62e
> --- /dev/null
> +++ b/drivers/net/pic32_eth.c
> @@ -0,0 +1,606 @@
> +/*
> + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + *
> + */
> +#include <common.h>
> +#include <errno.h>
> +#include <dm.h>
> +#include <net.h>
> +#include <miiphy.h>
> +#include <console.h>
> +#include <wait_bit.h>
> +#include <asm/gpio.h>
> +
> +#include "pic32_eth.h"
> +
> +#define MAX_RX_BUF_SIZE		1536
> +#define MAX_RX_DESCR		PKTBUFSRX
> +#define MAX_TX_DESCR		2
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +struct pic32eth_dev {
> +	struct eth_dma_desc rxd_ring[MAX_RX_DESCR];
> +	struct eth_dma_desc txd_ring[MAX_TX_DESCR];
> +	u32 rxd_idx; /* index of RX desc to read */
> +	/* regs */
> +	struct pic32_ectl_regs *ectl_regs;
> +	struct pic32_emac_regs *emac_regs;
> +	/* Phy */
> +	struct phy_device *phydev;
> +	phy_interface_t phyif;
> +	u32 phy_addr;
> +	struct gpio_desc rst_gpio;
> +};
> +
> +void __weak board_netphy_reset(void *dev)
> +{
> +	struct pic32eth_dev *priv = (struct pic32eth_dev *)dev;

the cast is not necessary

> +
> +	if (!dm_gpio_is_valid(&priv->rst_gpio))
> +		return;
> +
> +	/* phy reset */
> +	dm_gpio_set_value(&priv->rst_gpio, 0);
> +	udelay(300);
> +	dm_gpio_set_value(&priv->rst_gpio, 1);
> +	udelay(300);
> +}
> +
> +/* Initialize mii(MDIO) interface, discover which PHY is
> + * attached to the device, and configure it properly.
> + */
> +static int pic32_mii_init(struct pic32eth_dev *priv)
> +{
> +	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
> +	struct pic32_emac_regs *emac_p = priv->emac_regs;
> +
> +	/* board phy reset */
> +	board_netphy_reset(priv);
> +
> +	/* disable RX, TX & all transactions */
> +	writel(ETHCON_ON | ETHCON_TXRTS | ETHCON_RXEN, &ectl_p
> ->con1.clr);
> +
> +	/* wait till busy */
> +	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY,
> false,
> +		     CONFIG_SYS_HZ, false);
> +
> +	/* turn controller ON to access PHY over MII */
> +	writel(ETHCON_ON, &ectl_p->con1.set);
> +
> +	mdelay(10);
> +
> +	/* reset MAC */
> +	writel(EMAC_SOFTRESET, &emac_p->cfg1.set); /* reset assert
> */
> +	mdelay(10);
> +	writel(EMAC_SOFTRESET, &emac_p->cfg1.clr); /* reset deassert
> */
> +
> +	/* initialize MDIO/MII */
> +	if (priv->phyif == PHY_INTERFACE_MODE_RMII) {
> +		writel(EMAC_RMII_RESET, &emac_p->supp.set);
> +		mdelay(10);
> +		writel(EMAC_RMII_RESET, &emac_p->supp.clr);
> +	}
> +
> +	return pic32_mdio_init(PIC32_MDIO_NAME, (ulong)&emac_p
> ->mii);
> +}
> +
> +static int pic32_phy_init(struct pic32eth_dev *priv, struct udevice
> *dev)
> +{
> +	struct mii_dev *mii;
> +
> +	mii = miiphy_get_dev_by_name(PIC32_MDIO_NAME);
> +
> +	/* find & connect PHY */
> +	priv->phydev = phy_connect(mii, priv->phy_addr,
> +				   dev, priv->phyif);
> +	if (!priv->phydev) {
> +		printf("%s: %s: Error, PHY connect\n", __FILE__,
> __func__);
> +		return 0;
> +	}
> +
> +	/* Wait for phy to complete reset */
> +	mdelay(10);
> +
> +	/* configure supported modes */
> +	priv->phydev->supported = SUPPORTED_10baseT_Half |
> +				  SUPPORTED_10baseT_Full |
> +				  SUPPORTED_100baseT_Half |
> +				  SUPPORTED_100baseT_Full |
> +				  SUPPORTED_Autoneg;
> +
> +	priv->phydev->advertising = ADVERTISED_10baseT_Half |
> +				    ADVERTISED_10baseT_Full |
> +				    ADVERTISED_100baseT_Half |
> +				    ADVERTISED_100baseT_Full |
> +				    ADVERTISED_Autoneg;
> +
> +	priv->phydev->autoneg = AUTONEG_ENABLE;
> +
> +	return 0;
> +}
> +
> +/* Configure MAC based on negotiated speed and duplex
> + * reported by PHY.
> + */
> +static int pic32_mac_adjust_link(struct pic32eth_dev *priv)
> +{
> +	struct phy_device *phydev = priv->phydev;
> +	struct pic32_emac_regs *emac_p = priv->emac_regs;
> +
> +	if (!phydev->link) {
> +		printf("%s: No link.\n", phydev->dev->name);
> +		return -EINVAL;
> +	}
> +
> +	if (phydev->duplex) {
> +		writel(EMAC_FULLDUP, &emac_p->cfg2.set);
> +		writel(FULLDUP_GAP_TIME, &emac_p->ipgt.raw);
> +	} else {
> +		writel(EMAC_FULLDUP, &emac_p->cfg2.clr);
> +		writel(HALFDUP_GAP_TIME, &emac_p->ipgt.raw);
> +	}
> +
> +	switch (phydev->speed) {
> +	case SPEED_100:
> +		writel(EMAC_RMII_SPD100, &emac_p->supp.set);
> +		break;
> +	case SPEED_10:
> +		writel(EMAC_RMII_SPD100, &emac_p->supp.clr);
> +		break;
> +	default:
> +		printf("%s: Speed was bad\n", phydev->dev->name);
> +		return -EINVAL;
> +	}
> +
> +	printf("pic32eth: PHY is %s with %dbase%s, %s\n",
> +	       phydev->drv->name, phydev->speed,
> +	       (phydev->port == PORT_TP) ? "T" : "X",
> +	       (phydev->duplex) ? "full" : "half");
> +
> +	return 0;
> +}
> +
> +static void pic32_mac_init(struct pic32eth_dev *priv, u8 *macaddr)
> +{
> +	struct pic32_emac_regs *emac_p = priv->emac_regs;
> +	u32 stat = 0, v;
> +	u64 expire;
> +
> +	v = EMAC_TXPAUSE | EMAC_RXPAUSE | EMAC_RXENABLE;
> +	writel(v, &emac_p->cfg1.raw);
> +
> +	v = EMAC_EXCESS | EMAC_AUTOPAD | EMAC_PADENABLE |
> +	    EMAC_CRCENABLE | EMAC_LENGTHCK | EMAC_FULLDUP;
> +	writel(v, &emac_p->cfg2.raw);
> +
> +	/* recommended back-to-back inter-packet gap for 10 Mbps
> half duplex */
> +	writel(HALFDUP_GAP_TIME, &emac_p->ipgt.raw);
> +
> +	/* recommended non-back-to-back interpacket gap is 0xc12 */
> +	writel(0xc12, &emac_p->ipgr.raw);
> +
> +	/* recommended collision window retry limit is 0x370F */
> +	writel(0x370f, &emac_p->clrt.raw);
> +
> +	/* set maximum frame length: allow VLAN tagged frame */
> +	writel(0x600, &emac_p->maxf.raw);
> +
> +	/* set the mac address */
> +	writel(macaddr[0] | (macaddr[1] << 8), &emac_p->sa2.raw);
> +	writel(macaddr[2] | (macaddr[3] << 8), &emac_p->sa1.raw);
> +	writel(macaddr[4] | (macaddr[5] << 8), &emac_p->sa0.raw);
> +
> +	/* default, enable 10 Mbps operation */
> +	writel(EMAC_RMII_SPD100, &emac_p->supp.clr);
> +
> +	/* wait until link status UP or deadline elapsed */
> +	expire = get_ticks() + get_tbclk() * 2;
> +	for (; get_ticks() < expire;) {
> +		stat = phy_read(priv->phydev, priv->phy_addr,
> MII_BMSR);
> +		if (stat & BMSR_LSTATUS)
> +			break;
> +	}
> +
> +	if (!(stat & BMSR_LSTATUS))
> +		printf("MAC: Link is DOWN!\n");
> +
> +	/* delay to stabilize before any tx/rx */
> +	mdelay(10);
> +}
> +
> +static void pic32_mac_reset(struct pic32eth_dev *priv)
> +{
> +	struct pic32_emac_regs *emac_p = priv->emac_regs;
> +	struct mii_dev *mii;
> +
> +	/* Reset MAC */
> +	writel(EMAC_SOFTRESET, &emac_p->cfg1.raw);
> +	mdelay(10);
> +
> +	/* clear reset */
> +	writel(0, &emac_p->cfg1.raw);
> +
> +	/* Reset MII */
> +	mii = priv->phydev->bus;
> +	if (mii && mii->reset)
> +		mii->reset(mii);
> +}
> +
> +/* initializes the MAC and PHY, then establishes a link */
> +static void pic32_ctrl_reset(struct pic32eth_dev *priv)
> +{
> +	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
> +	u32 v;
> +
> +	/* disable RX, TX & any other transactions */
> +	writel(ETHCON_ON | ETHCON_TXRTS | ETHCON_RXEN, &ectl_p
> ->con1.clr);
> +
> +	/* wait till busy */
> +	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY,
> false,
> +		     CONFIG_SYS_HZ, false);
> +	/* decrement received buffcnt to zero. */
> +	while (readl(&ectl_p->stat.raw) & ETHSTAT_BUFCNT)
> +		writel(ETHCON_BUFCDEC, &ectl_p->con1.set);
> +
> +	/* clear any existing interrupt event */
> +	writel(0xffffffff, &ectl_p->irq.clr);
> +
> +	/* clear RX/TX start address */
> +	writel(0xffffffff, &ectl_p->txst.clr);
> +	writel(0xffffffff, &ectl_p->rxst.clr);
> +
> +	/* clear the receive filters */
> +	writel(0x00ff, &ectl_p->rxfc.clr);
> +
> +	/* set the receive filters
> +	 * ETH_FILT_CRC_ERR_REJECT
> +	 * ETH_FILT_RUNT_REJECT
> +	 * ETH_FILT_UCAST_ACCEPT
> +	 * ETH_FILT_MCAST_ACCEPT
> +	 * ETH_FILT_BCAST_ACCEPT
> +	 */
> +	v = ETHRXFC_BCEN | ETHRXFC_MCEN | ETHRXFC_UCEN |
> +	    ETHRXFC_RUNTEN | ETHRXFC_CRCOKEN;
> +	writel(v, &ectl_p->rxfc.set);
> +
> +	/* turn controller ON to access PHY over MII */
> +	writel(ETHCON_ON, &ectl_p->con1.set);
> +}
> +
> +static void pic32_rx_desc_init(struct pic32eth_dev *priv)
> +{
> +	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
> +	struct eth_dma_desc *rxd;
> +	u32 idx, bufsz;
> +
> +	priv->rxd_idx = 0;
> +	for (idx = 0; idx < MAX_RX_DESCR; idx++) {
> +		rxd = &priv->rxd_ring[idx];
> +
> +		/* hw owned */
> +		rxd->hdr = EDH_NPV | EDH_EOWN | EDH_STICKY;
> +
> +		/* packet buffer address */
> +		rxd->data_buff = virt_to_phys(net_rx_packets[idx]);
> +
> +		/* link to next desc */
> +		rxd->next_ed = virt_to_phys(rxd + 1);
> +
> +		/* reset status */
> +		rxd->stat1 = 0;
> +		rxd->stat2 = 0;
> +
> +		/* decrement bufcnt */
> +		writel(ETHCON_BUFCDEC, &ectl_p->con1.set);
> +	}
> +
> +	/* link last descr to beginning of list */
> +	rxd->next_ed = virt_to_phys(&priv->rxd_ring[0]);
> +
> +	/* flush rx ring */
> +	__dcache_flush(priv->rxd_ring, sizeof(priv->rxd_ring));
> +
> +	/* set rx desc-ring start address */
> +	writel((ulong)virt_to_phys(&priv->rxd_ring[0]), &ectl_p
> ->rxst.raw);
> +
> +	/* RX Buffer size */
> +	bufsz = readl(&ectl_p->con2.raw);
> +	bufsz &= ~(ETHCON_RXBUFSZ << ETHCON_RXBUFSZ_SHFT);
> +	bufsz |= ((MAX_RX_BUF_SIZE / 16) << ETHCON_RXBUFSZ_SHFT);
> +	writel(bufsz, &ectl_p->con2.raw);
> +
> +	/* enable the receiver in hardware which allows hardware
> +	 * to DMA received pkts to the descriptor pointer address.
> +	 */
> +	writel(ETHCON_RXEN, &ectl_p->con1.set);
> +}
> +
> +static int pic32_eth_start(struct udevice *dev)
> +{
> +	struct eth_pdata *pdata = dev_get_platdata(dev);
> +	struct pic32eth_dev *priv = dev_get_priv(dev);
> +
> +	/* controller */
> +	pic32_ctrl_reset(priv);
> +
> +	/* reset MAC */
> +	pic32_mac_reset(priv);
> +
> +	/* configure PHY */
> +	phy_config(priv->phydev);
> +
> +	/* initialize MAC */
> +	pic32_mac_init(priv, &pdata->enetaddr[0]);
> +
> +	/* init RX descriptor; TX descriptors are handled in xmit */
> +	pic32_rx_desc_init(priv);
> +
> +	/* Start up & update link status of PHY */
> +	phy_startup(priv->phydev);
> +
> +	/* adjust mac with phy link status */
> +	return pic32_mac_adjust_link(priv);
> +}
> +
> +static void pic32_eth_stop(struct udevice *dev)
> +{
> +	struct pic32eth_dev *priv = dev_get_priv(dev);
> +	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
> +	struct pic32_emac_regs *emac_p = priv->emac_regs;
> +
> +	/* Reset the phy if the controller is enabled */
> +	if (readl(&ectl_p->con1.raw) & ETHCON_ON)
> +		phy_reset(priv->phydev);
> +
> +	/* Shut down the PHY */
> +	phy_shutdown(priv->phydev);
> +
> +	/* Stop rx/tx */
> +	writel(ETHCON_TXRTS | ETHCON_RXEN, &ectl_p->con1.clr);
> +	mdelay(10);
> +
> +	/* reset MAC */
> +	writel(EMAC_SOFTRESET, &emac_p->cfg1.raw);
> +
> +	/* clear reset */
> +	writel(0, &emac_p->cfg1.raw);
> +	mdelay(10);
> +
> +	/* disable controller */
> +	writel(ETHCON_ON, &ectl_p->con1.clr);
> +	mdelay(10);
> +
> +	/* wait until everything is down */
> +	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY,
> false,
> +		     2 * CONFIG_SYS_HZ, false);
> +
> +	/* clear any existing interrupt event */
> +	writel(0xffffffff, &ectl_p->irq.clr);
> +}
> +
> +static int pic32_eth_send(struct udevice *dev, void *packet, int
> length)
> +{
> +	struct pic32eth_dev *priv = dev_get_priv(dev);
> +	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
> +	struct eth_dma_desc *txd;
> +	u64 deadline;
> +
> +	txd = &priv->txd_ring[0];
> +
> +	/* set proper flags & length in descriptor header */
> +	txd->hdr = EDH_SOP | EDH_EOP | EDH_EOWN |
> EDH_BCOUNT(length);
> +
> +	/* pass buffer address to hardware */
> +	txd->data_buff = virt_to_phys(packet);
> +
> +	debug("%s: %d / .hdr %x, .data_buff %x, .stat %x, .nexted
> %x\n",
> +	      __func__, __LINE__, txd->hdr, txd->data_buff, txd
> ->stat2,
> +	      txd->next_ed);
> +
> +	/* cache flush (packet) */
> +	__dcache_flush(packet, length);
> +
> +	/* cache flush (txd) */
> +	__dcache_flush(txd, sizeof(*txd));
> +
> +	/* pass descriptor table base to h/w */
> +	writel(virt_to_phys(txd), &ectl_p->txst.raw);
> +
> +	/* ready to send enabled, hardware can now send the
> packet(s) */
> +	writel(ETHCON_TXRTS | ETHCON_ON, &ectl_p->con1.set);
> +
> +	/* wait until tx has completed and h/w has released
> ownership
> +	 * of the tx descriptor or timeout elapsed.
> +	 */
> +	deadline = get_ticks() + get_tbclk();
> +	for (;;) {
> +		/* check timeout */
> +		if (get_ticks() > deadline)
> +			return -ETIMEDOUT;
> +
> +		if (ctrlc())
> +			return -EINTR;
> +
> +		/* tx completed ? */
> +		if (readl(&ectl_p->con1.raw) & ETHCON_TXRTS) {
> +			udelay(1);
> +			continue;
> +		}
> +
> +		/* h/w not released ownership yet? */
> +		__dcache_invalidate(txd, sizeof(*txd));
> +		if (!(txd->hdr & EDH_EOWN))
> +			break;
> +	}
> +
> +	return 0;
> +}
> +
> +static int pic32_eth_recv(struct udevice *dev, int flags, uchar
> **packetp)
> +{
> +	struct pic32eth_dev *priv = dev_get_priv(dev);
> +	struct eth_dma_desc *rxd;
> +	u32 idx = priv->rxd_idx;
> +	u32 rx_count;
> +
> +	/* find the next ready to receive */
> +	rxd = &priv->rxd_ring[idx];
> +
> +	__dcache_invalidate(rxd, sizeof(*rxd));
> +	/* check if owned by MAC */
> +	if (rxd->hdr & EDH_EOWN)
> +		return -EAGAIN;
> +
> +	/* Sanity check on header: SOP and EOP  */
> +	if ((rxd->hdr & (EDH_SOP | EDH_EOP)) != (EDH_SOP | EDH_EOP))
> {
> +		printf("%s: %s, rx pkt across multiple descr\n",
> +		       __FILE__, __func__);
> +		return 0;
> +	}
> +
> +	debug("%s: %d /idx %i, hdr=%x, data_buff %x, stat %x, nexted
> %x\n",
> +	      __func__, __LINE__, idx, rxd->hdr,
> +	      rxd->data_buff, rxd->stat2, rxd->next_ed);
> +
> +	/* Sanity check on rx_stat: OK, CRC */
> +	if (!RSV_RX_OK(rxd->stat2) || RSV_CRC_ERR(rxd->stat2)) {
> +		debug("%s: %s: Error, rx problem detected\n",
> +		      __FILE__, __func__);
> +		return 0;
> +	}
> +
> +	/* invalidate dcache */
> +	rx_count = RSV_RX_COUNT(rxd->stat2);
> +	__dcache_invalidate(net_rx_packets[idx], rx_count);
> +
> +	/* Pass the packet to protocol layer */
> +	*packetp = net_rx_packets[idx];
> +
> +	/* increment number of bytes rcvd (ignore CRC) */
> +	return rx_count - 4;
> +}
> +
> +static int pic32_eth_free_pkt(struct udevice *dev, uchar *packet,
> int length)
> +{
> +	struct pic32eth_dev *priv = dev_get_priv(dev);
> +	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
> +	struct eth_dma_desc *rxd;
> +	int idx = priv->rxd_idx;
> +
> +	/* sanity check */
> +	if (packet != net_rx_packets[idx]) {
> +		printf("rxd_id %d: packet is not matched,\n", idx);
> +		return -EAGAIN;
> +	}
> +
> +	/* prepare for receive */
> +	rxd = &priv->rxd_ring[idx];
> +	rxd->hdr = EDH_STICKY | EDH_NPV | EDH_EOWN;
> +
> +	__dcache_flush(rxd, sizeof(*rxd));
> +
> +	/* decrement rx pkt count */
> +	writel(ETHCON_BUFCDEC, &ectl_p->con1.set);
> +
> +	debug("%s: %d / idx %i, hdr %x, data_buff %x, stat %x,
> nexted %x\n",
> +	      __func__, __LINE__, idx, rxd->hdr, rxd->data_buff,
> +	      rxd->stat2, rxd->next_ed);
> +
> +	priv->rxd_idx = (priv->rxd_idx + 1) % MAX_RX_DESCR;
> +
> +	return 0;
> +}
> +
> +static const struct eth_ops pic32_eth_ops = {
> +	.start		= pic32_eth_start,
> +	.send		= pic32_eth_send,
> +	.recv		= pic32_eth_recv,
> +	.free_pkt	= pic32_eth_free_pkt,
> +	.stop		= pic32_eth_stop,
> +};
> +
> +static int pic32_eth_probe(struct udevice *dev)
> +{
> +	struct eth_pdata *pdata = dev_get_platdata(dev);

your driver private data should be stored in struct pic32eth_dev

> +	struct pic32eth_dev *priv = dev_get_priv(dev);
> +	const char *phy_mode;
> +	void __iomem *iobase;
> +	fdt_addr_t addr;
> +	fdt_size_t size;
> +	int offset = 0;
> +	int phy_addr = -1;
> +
> +	addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset,
> "reg", &size);
> +	if (addr == FDT_ADDR_T_NONE)
> +		return -EINVAL;
> +
> +	iobase = ioremap(addr, size);
> +	if (!iobase)
> +		return -EINVAL;

you can drop this check. ioremap() always returns a mapped address.

> +
> +	pdata->iobase = (phys_addr_t)addr;
> +
> +	/* get phy mode */
> +	pdata->phy_interface = -1;
> +	phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy
> -mode", NULL);
> +	if (phy_mode)
> +		pdata->phy_interface =
> phy_get_interface_by_name(phy_mode);
> +	if (pdata->phy_interface == -1) {
> +		debug("%s: Invalid PHY interface '%s'\n", __func__,
> phy_mode);
> +		return -EINVAL;
> +	}

your driver private data should be stored in struct pic32eth_dev. Only
if a arch/SoC does not support device-tree, platdata have to be
initialized with PHY address and PHY interface in the board code. Also
form a drivers point of view, platdata is read-only and provides board
-specific configuration for the driver.

> +
> +	/* get phy addr */
> +	offset = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset,
> +				       "phy-handle");
> +	if (offset > 0)
> +		phy_addr = fdtdec_get_int(gd->fdt_blob, offset,
> "reg", -1);
> +
> +	/* phy reset gpio */
> +	gpio_request_by_name_nodev(gd->fdt_blob, dev->of_offset,
> +				   "reset-gpios", 0,
> +				   &priv->rst_gpio, GPIOD_IS_OUT);
> +
> +	priv->phyif	= pdata->phy_interface;
> +	priv->phy_addr	= phy_addr;
> +	priv->ectl_regs	= iobase;
> +	priv->emac_regs	= iobase + PIC32_EMAC1CFG1;
> +
> +	pic32_mii_init(priv);
> +
> +	return pic32_phy_init(priv, dev);
> +}
> +
> +static int pic32_eth_remove(struct udevice *dev)
> +{
> +	struct pic32eth_dev *priv = dev_get_priv(dev);
> +	struct mii_dev *bus;
> +
> +	dm_gpio_free(dev, &priv->rst_gpio);
> +	phy_shutdown(priv->phydev);
> +	free(priv->phydev);
> +	bus = miiphy_get_dev_by_name(PIC32_MDIO_NAME);
> +	mdio_unregister(bus);
> +	mdio_free(bus);
> +	iounmap(priv->ectl_regs);
> +	return 0;
> +}
> +
> +static const struct udevice_id pic32_eth_ids[] = {
> +	{ .compatible = "microchip,pic32mzda-eth" },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(pic32_ethernet) = {
> +	.name			= "pic32_ethernet",
> +	.id			= UCLASS_ETH,
> +	.of_match		= pic32_eth_ids,
> +	.probe			= pic32_eth_probe,
> +	.remove			= pic32_eth_remove,
> +	.ops			= &pic32_eth_ops,
> +	.priv_auto_alloc_size	= sizeof(struct pic32eth_dev),
> +	.platdata_auto_alloc_size	= sizeof(struct eth_pdata),
> +};
> diff --git a/drivers/net/pic32_eth.h b/drivers/net/pic32_eth.h
> new file mode 100644
> index 0000000..4dd443b
> --- /dev/null
> +++ b/drivers/net/pic32_eth.h
> @@ -0,0 +1,171 @@
> +/*
> + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + *
> + */
> +
> +#ifndef __MICROCHIP_PIC32_ETH_H_
> +#define __MICROCHIP_PIC32_ETH_H_
> +
> +#include <mach/pic32.h>
> +
> +/* Ethernet */
> +struct pic32_ectl_regs {
> +	struct pic32_reg_atomic con1; /* 0x00 */
> +	struct pic32_reg_atomic con2; /* 0x10 */
> +	struct pic32_reg_atomic txst; /* 0x20 */
> +	struct pic32_reg_atomic rxst; /* 0x30 */
> +	struct pic32_reg_atomic ht0;  /* 0x40 */
> +	struct pic32_reg_atomic ht1;  /* 0x50 */
> +	struct pic32_reg_atomic pmm0; /* 0x60 */
> +	struct pic32_reg_atomic pmm1; /* 0x70 */
> +	struct pic32_reg_atomic pmcs; /* 0x80 */
> +	struct pic32_reg_atomic pmo;  /* 0x90 */
> +	struct pic32_reg_atomic rxfc; /* 0xa0 */
> +	struct pic32_reg_atomic rxwm; /* 0xb0 */
> +	struct pic32_reg_atomic ien;  /* 0xc0 */
> +	struct pic32_reg_atomic irq;  /* 0xd0 */
> +	struct pic32_reg_atomic stat; /* 0xe0 */
> +};
> +
> +struct pic32_mii_regs {
> +	struct pic32_reg_atomic mcfg; /* 0x280 */
> +	struct pic32_reg_atomic mcmd; /* 0x290 */
> +	struct pic32_reg_atomic madr; /* 0x2a0 */
> +	struct pic32_reg_atomic mwtd; /* 0x2b0 */
> +	struct pic32_reg_atomic mrdd; /* 0x2c0 */
> +	struct pic32_reg_atomic mind; /* 0x2d0 */
> +};
> +
> +struct pic32_emac_regs {
> +	struct pic32_reg_atomic cfg1; /* 0x200*/
> +	struct pic32_reg_atomic cfg2; /* 0x210*/
> +	struct pic32_reg_atomic ipgt; /* 0x220*/
> +	struct pic32_reg_atomic ipgr; /* 0x230*/
> +	struct pic32_reg_atomic clrt; /* 0x240*/
> +	struct pic32_reg_atomic maxf; /* 0x250*/
> +	struct pic32_reg_atomic supp; /* 0x260*/
> +	struct pic32_reg_atomic test; /* 0x270*/
> +	struct pic32_mii_regs mii;    /* 0x280 - 0x2d0 */
> +	struct pic32_reg_atomic res1; /* 0x2e0 */
> +	struct pic32_reg_atomic res2; /* 0x2f0 */
> +	struct pic32_reg_atomic sa0;  /* 0x300 */
> +	struct pic32_reg_atomic sa1;  /* 0x310 */
> +	struct pic32_reg_atomic sa2;  /* 0x320 */
> +};
> +
> +/* ETHCON1 Reg field */
> +#define ETHCON_BUFCDEC		BIT(0)
> +#define ETHCON_RXEN		BIT(8)
> +#define ETHCON_TXRTS		BIT(9)
> +#define ETHCON_ON		BIT(15)
> +
> +/* ETHCON2 Reg field */
> +#define ETHCON_RXBUFSZ		0x7f
> +#define ETHCON_RXBUFSZ_SHFT	0x4
> +
> +/* ETHSTAT Reg field */
> +#define ETHSTAT_BUSY		BIT(7)
> +#define ETHSTAT_BUFCNT		0x00ff0000
> +
> +/* ETHRXFC Register fields */
> +#define ETHRXFC_BCEN		BIT(0)
> +#define ETHRXFC_MCEN		BIT(1)
> +#define ETHRXFC_UCEN		BIT(3)
> +#define ETHRXFC_RUNTEN		BIT(4)
> +#define ETHRXFC_CRCOKEN		BIT(5)
> +
> +/* EMAC1CFG1 register offset */
> +#define PIC32_EMAC1CFG1		0x0200
> +
> +/* EMAC1CFG1 register fields */
> +#define EMAC_RXENABLE		BIT(0)
> +#define EMAC_RXPAUSE		BIT(2)
> +#define EMAC_TXPAUSE		BIT(3)
> +#define EMAC_SOFTRESET		BIT(15)
> +
> +/* EMAC1CFG2 register fields */
> +#define EMAC_FULLDUP		BIT(0)
> +#define EMAC_LENGTHCK		BIT(1)
> +#define EMAC_CRCENABLE		BIT(4)
> +#define EMAC_PADENABLE		BIT(5)
> +#define EMAC_AUTOPAD		BIT(7)
> +#define EMAC_EXCESS		BIT(14)
> +
> +/* EMAC1IPGT register magic */
> +#define FULLDUP_GAP_TIME	0x15
> +#define HALFDUP_GAP_TIME	0x12
> +
> +/* EMAC1SUPP register fields */
> +#define EMAC_RMII_SPD100	BIT(8)
> +#define EMAC_RMII_RESET		BIT(11)
> +
> +/* MII Management Configuration Register */
> +#define MIIMCFG_RSTMGMT		BIT(15)
> +#define MIIMCFG_CLKSEL_DIV40	0x0020	/* 100Mhz / 40 */
> +
> +/* MII Management Command Register */
> +#define MIIMCMD_READ		BIT(0)
> +#define MIIMCMD_SCAN		BIT(1)
> +
> +/* MII Management Address Register */
> +#define MIIMADD_REGADDR		0x1f
> +#define MIIMADD_REGADDR_SHIFT	0
> +#define MIIMADD_PHYADDR_SHIFT	8
> +
> +/* MII Management Indicator Register */
> +#define MIIMIND_BUSY		BIT(0)
> +#define MIIMIND_NOTVALID	BIT(2)
> +#define MIIMIND_LINKFAIL	BIT(3)
> +
> +/* Packet Descriptor */
> +/* Received Packet Status */
> +#define _RSV1_PKT_CSUM		0xffff
> +#define _RSV2_CRC_ERR		BIT(20)
> +#define _RSV2_LEN_ERR		BIT(21)
> +#define _RSV2_RX_OK		BIT(23)
> +#define _RSV2_RX_COUNT		0xffff
> +
> +#define RSV_RX_CSUM(__rsv1)	((__rsv1) & _RSV1_PKT_CSUM)
> +#define RSV_RX_COUNT(__rsv2)	((__rsv2) & _RSV2_RX_COUNT)
> +#define RSV_RX_OK(__rsv2)	((__rsv2) & _RSV2_RX_OK)
> +#define RSV_CRC_ERR(__rsv2)	((__rsv2) & _RSV2_CRC_ERR)
> +
> +/* Ethernet Hardware Descriptor Header bits */
> +#define EDH_EOWN		BIT(7)
> +#define EDH_NPV			BIT(8)
> +#define EDH_STICKY		BIT(9)
> +#define _EDH_BCOUNT		0x07ff0000
> +#define EDH_EOP			BIT(30)
> +#define EDH_SOP			BIT(31)
> +#define EDH_BCOUNT_SHIFT	16
> +#define EDH_BCOUNT(len)		((len) << EDH_BCOUNT_SHIFT)
> +
> +/* Ethernet Hardware Descriptors
> + * ref: PIC32 Family Reference Manual Table 35-7
> + * This structure represents the layout of the DMA
> + * memory shared between the CPU and the Ethernet
> + * controller.
> + */
> +/* TX/RX DMA descriptor */
> +struct eth_dma_desc {
> +	u32 hdr;	/* header */
> +	u32 data_buff;	/* data buffer address */
> +	u32 stat1;	/* transmit/receive packet status */
> +	u32 stat2;	/* transmit/receive packet status */
> +	u32 next_ed;	/* next descriptor */
> +};
> +
> +/* cache operation helper */
> +#define __dcache_flush(__a, __l) \
> +	flush_dcache_range((ulong)(__a),  ((__l) + (ulong)(__a)))
> +
> +#define __dcache_invalidate(__a, __l) \
> +	invalidate_dcache_range((ulong)(__a),  ((__l) +
> (ulong)(__a)))
> +
> +#define PIC32_MDIO_NAME "PIC32_EMAC"
> +
> +int pic32_mdio_init(const char *name, ulong ioaddr);
> +
> +#endif /* __MICROCHIP_PIC32_ETH_H_*/
> diff --git a/drivers/net/pic32_mdio.c b/drivers/net/pic32_mdio.c
> new file mode 100644
> index 0000000..578fc96
> --- /dev/null
> +++ b/drivers/net/pic32_mdio.c
> @@ -0,0 +1,121 @@
> +/*
> + * pic32_mdio.c: PIC32 MDIO/MII driver, part of pic32_eth.c.
> + *
> + * Copyright 2015 Microchip Inc.
> + *	Purna Chandra Mandal <purna.mandal@microchip.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +#include <common.h>
> +#include <phy.h>
> +#include <miiphy.h>
> +#include <errno.h>
> +#include <wait_bit.h>
> +#include <asm/io.h>
> +#include "pic32_eth.h"
> +
> +static int pic32_mdio_write(struct mii_dev *bus,
> +			    int addr, int dev_addr,
> +			    int reg, u16 value)
> +{
> +	u32 v;
> +	struct pic32_mii_regs *mii_regs = bus->priv;
> +
> +	/* Wait for the previous operation to finish */
> +	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
> +		     false, CONFIG_SYS_HZ, true);
> +
> +	/* Put phyaddr and regaddr into MIIMADD */
> +	v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg &
> MIIMADD_REGADDR);
> +	writel(v, &mii_regs->madr.raw);
> +
> +	/* Initiate a write command */
> +	writel(value, &mii_regs->mwtd.raw);
> +
> +	/* Wait 30 clock cycles for busy flag to be set */
> +	udelay(12);
> +
> +	/* Wait for write to complete */
> +	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
> +		     false, CONFIG_SYS_HZ, true);
> +
> +	return 0;
> +}
> +
> +static int pic32_mdio_read(struct mii_dev *bus, int addr, int
> devaddr, int reg)
> +{
> +	u32 v;
> +	struct pic32_mii_regs *mii_regs = bus->priv;
> +
> +	/* Wait for the previous operation to finish */
> +	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
> +		     false, CONFIG_SYS_HZ, true);
> +
> +	/* Put phyaddr and regaddr into MIIMADD */
> +	v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg &
> MIIMADD_REGADDR);
> +	writel(v, &mii_regs->madr.raw);
> +
> +	/* Initiate a read command */
> +	writel(MIIMCMD_READ, &mii_regs->mcmd.raw);
> +
> +	/* Wait 30 clock cycles for busy flag to be set */
> +	udelay(12);
> +
> +	/* Wait for read to complete */
> +	wait_for_bit(__func__, &mii_regs->mind.raw,
> +		     MIIMIND_NOTVALID | MIIMIND_BUSY,
> +		     false, CONFIG_SYS_HZ, false);
> +
> +	/* Clear the command register */
> +	writel(0, &mii_regs->mcmd.raw);
> +
> +	/* Grab the value read from the PHY */
> +	v = readl(&mii_regs->mrdd.raw);
> +	return v;
> +}
> +
> +static int pic32_mdio_reset(struct mii_dev *bus)
> +{
> +	struct pic32_mii_regs *mii_regs = bus->priv;
> +
> +	/* Reset MII (due to new addresses) */
> +	writel(MIIMCFG_RSTMGMT, &mii_regs->mcfg.raw);
> +
> +	/* Wait for the operation to finish */
> +	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
> +		     false, CONFIG_SYS_HZ, true);
> +
> +	/* Clear reset bit */
> +	writel(0, &mii_regs->mcfg);
> +
> +	/* Wait for the operation to finish */
> +	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
> +		     false, CONFIG_SYS_HZ, true);
> +
> +	/* Set the MII Management Clock (MDC) - no faster than 2.5
> MHz */
> +	writel(MIIMCFG_CLKSEL_DIV40, &mii_regs->mcfg.raw);
> +
> +	/* Wait for the operation to finish */
> +	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
> +		     false, CONFIG_SYS_HZ, true);
> +	return 0;
> +}
> +
> +int pic32_mdio_init(const char *name, ulong ioaddr)
> +{
> +	struct mii_dev *bus;
> +
> +	bus = mdio_alloc();
> +	if (!bus) {
> +		printf("Failed to allocate PIC32-MDIO bus\n");
> +		return -ENOMEM;
> +	}
> +
> +	bus->read = pic32_mdio_read;
> +	bus->write = pic32_mdio_write;
> +	bus->reset = pic32_mdio_reset;
> +	strncpy(bus->name, name, sizeof(bus->name));
> +	bus->priv = (void *)ioaddr;
> +
> +	return mdio_register(bus);
> +}
-- 
- Daniel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 07/14] drivers: ddr: Add DDR2 SDRAM controller driver for Microchip PIC32.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 07/14] drivers: ddr: Add DDR2 SDRAM controller driver for Microchip PIC32 Purna Chandra Mandal
  2016-01-13 13:53   ` Daniel Schwierzeck
  2016-01-13 14:55   ` Tom Rini
@ 2016-01-13 20:09   ` Simon Glass
  2 siblings, 0 replies; 62+ messages in thread
From: Simon Glass @ 2016-01-13 20:09 UTC (permalink / raw)
  To: u-boot

On 12 January 2016 at 03:18, Purna Chandra Mandal
<purna.mandal@microchip.com> wrote:
> This driver initializes PIC32 DDR2 SDRAM controller and internal DDR2 Phy module.
> DDR2 controller operates in half-rate mode (upto 533MHZ frequency).
>
> Signed-off-by: Paul Thacker <paul.thacker@microchip.com>
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
>
>
> ---
>
> Changes in v3:
> - annotating fixed table with const
> - fix camel-case in ddr2 timing parameters
> - fix cmd index parameter of host_load_cmd().
> - fix compilation warning
>
> Changes in v2:
> - move ddr2 initialization from board/microchip/ to drivers/ddr/microchip
>
>  arch/mips/mach-pic32/include/mach/ddr.h |  32 ++++
>  drivers/Makefile                        |   1 +
>  drivers/ddr/microchip/Makefile          |   6 +
>  drivers/ddr/microchip/ddr2.c            | 278 ++++++++++++++++++++++++++++++++
>  drivers/ddr/microchip/ddr2_regs.h       | 148 +++++++++++++++++
>  drivers/ddr/microchip/ddr2_timing.h     |  65 ++++++++
>  6 files changed, 530 insertions(+)
>  create mode 100644 arch/mips/mach-pic32/include/mach/ddr.h
>  create mode 100644 drivers/ddr/microchip/Makefile
>  create mode 100644 drivers/ddr/microchip/ddr2.c
>  create mode 100644 drivers/ddr/microchip/ddr2_regs.h
>  create mode 100644 drivers/ddr/microchip/ddr2_timing.h

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 06/14] drivers: serial: add driver for Microchip PIC32 UART controller.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 06/14] drivers: serial: add driver for Microchip PIC32 UART controller Purna Chandra Mandal
  2016-01-13 13:49   ` Daniel Schwierzeck
  2016-01-13 14:55   ` Tom Rini
@ 2016-01-13 20:09   ` Simon Glass
  2016-01-14  6:14     ` Purna Chandra Mandal
  2 siblings, 1 reply; 62+ messages in thread
From: Simon Glass @ 2016-01-13 20:09 UTC (permalink / raw)
  To: u-boot

Hi Purna,

On 12 January 2016 at 03:18, Purna Chandra Mandal
<purna.mandal@microchip.com> wrote:
>
> From: Paul Thacker <paul.thacker@microchip.com>
>
> This adds PIC32 UART controller support based on driver model.
>
> Signed-off-by: Paul Thacker <paul.thacker@microchip.com>
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
>
>
> ---
>
> Changes in v3:
> - remove ofdata_to_platdata, and replace platdata with priv
> - remove special handling of '\r' as being handled by serial-uclass
> - remove loop to wait for space in tx buffer before pumping char
>
> Changes in v2:
> - fix missing/corrupted chars during baud rate change
> - remove loop until any char is avaialbale in getc()
>
>  .../serial/microchip,pic32-uart.txt                |   5 +
>  drivers/serial/Kconfig                             |  13 ++
>  drivers/serial/Makefile                            |   1 +
>  drivers/serial/serial_pic32.c                      | 199 +++++++++++++++++++++
>  4 files changed, 218 insertions(+)
>  create mode 100644 doc/device-tree-bindings/serial/microchip,pic32-uart.txt
>  create mode 100644 drivers/serial/serial_pic32.c
>

Reviewed-by: Simon Glass <sjg@chromium.org>

One nit/question below.

> diff --git a/doc/device-tree-bindings/serial/microchip,pic32-uart.txt b/doc/device-tree-bindings/serial/microchip,pic32-uart.txt
> new file mode 100644
> index 0000000..f00e215
> --- /dev/null
> +++ b/doc/device-tree-bindings/serial/microchip,pic32-uart.txt
> @@ -0,0 +1,5 @@
> +* Microchip PIC32 serial UART
> +
> +Required properties:
> +- compatible: must be "microchip,pic32mzda-uart".
> +- reg: exactly one register range.
> diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
> index 1fc287e..9763ea1 100644
> --- a/drivers/serial/Kconfig
> +++ b/drivers/serial/Kconfig
> @@ -107,6 +107,14 @@ config DEBUG_UART_APBUART
>           will need to provide parameters to make this work. The driver will
>           be available until the real driver model serial is running.
>
> +config DEBUG_UART_PIC32
> +       bool "Microchip PIC32"
> +       help
> +         Select this to enable a debug UART using the serial_pic32 driver. You
> +         will need to provide parameters to make this work. The driver will
> +         be available until the real driver model serial is running.
> +
> +
>  endchoice
>
>  config DEBUG_UART_BASE
> @@ -223,4 +231,9 @@ config UNIPHIER_SERIAL
>           If you have a UniPhier based board and want to use the on-chip
>           serial ports, say Y to this option. If unsure, say N.
>
> +config PIC32_SERIAL
> +       bool "Support for Microchip PIC32 on-chip UART"
> +       help
> +         Support for the UART found on Microchip PIC32 SoC's.
> +
>  endmenu
> diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
> index dd87147..57cd38b 100644
> --- a/drivers/serial/Makefile
> +++ b/drivers/serial/Makefile
> @@ -41,6 +41,7 @@ obj-$(CONFIG_MXS_AUART) += mxs_auart.o
>  obj-$(CONFIG_ARC_SERIAL) += serial_arc.o
>  obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o
>  obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o
> +obj-$(CONFIG_PIC32_SERIAL) += serial_pic32.o
>
>  ifndef CONFIG_SPL_BUILD
>  obj-$(CONFIG_USB_TTY) += usbtty.o
> diff --git a/drivers/serial/serial_pic32.c b/drivers/serial/serial_pic32.c
> new file mode 100644
> index 0000000..ee9d056
> --- /dev/null
> +++ b/drivers/serial/serial_pic32.c
> @@ -0,0 +1,199 @@
> +/*
> + * (c) 2015 Paul Thacker <paul.thacker@microchip.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + *
> + */
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <serial.h>
> +#include <wait_bit.h>
> +#include <mach/pic32.h>
> +#include <dt-bindings/clock/microchip,clock.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* UART Control Registers */
> +#define U_MOD          0x00
> +#define U_MODCLR       (U_MOD + _CLR_OFFSET)
> +#define U_MODSET       (U_MOD + _SET_OFFSET)
> +#define U_STA          0x10
> +#define U_STACLR       (U_STA + _CLR_OFFSET)
> +#define U_STASET       (U_STA + _SET_OFFSET)
> +#define U_TXR          0x20
> +#define U_RXR          0x30
> +#define U_BRG          0x40
> +
> +/* U_MOD bits */
> +#define UART_ENABLE            BIT(15)
> +
> +/* U_STA bits */
> +#define UART_RX_ENABLE         BIT(12)
> +#define UART_TX_BRK            BIT(11)
> +#define UART_TX_ENABLE         BIT(10)
> +#define UART_TX_FULL           BIT(9)
> +#define UART_TX_EMPTY          BIT(8)
> +#define UART_RX_OERR           BIT(1)
> +#define UART_RX_DATA_AVAIL     BIT(0)
> +
> +struct pic32_uart_priv {
> +       void __iomem *base;
> +       ulong uartclk;
> +};
> +
> +/*
> + * Initialize the serial port with the given baudrate.
> + * The settings are always 8 data bits, no parity, 1 stop bit, no start bits.
> + */
> +static int pic32_serial_init(void __iomem *base, ulong clk, u32 baudrate)
> +{
> +       u32 div = DIV_ROUND_CLOSEST(clk, baudrate * 16);
> +
> +       /* wait for TX FIFO to empty */
> +       wait_for_bit(__func__, base + U_STA, UART_TX_EMPTY,
> +                    true, CONFIG_SYS_HZ, false);
> +
> +       /* send break */
> +       writel(UART_TX_BRK, base + U_STASET);
> +
> +       /* disable and clear mode */
> +       writel(0, base + U_MOD);
> +       writel(0, base + U_STA);
> +
> +       /* set baud rate generator */
> +       writel(div - 1, base + U_BRG);
> +
> +       /* enable the UART for TX and RX */
> +       writel(UART_TX_ENABLE | UART_RX_ENABLE, base + U_STASET);
> +
> +       /* enable the UART */
> +       writel(UART_ENABLE, base + U_MODSET);
> +       return 0;
> +}
> +
> +/* Check number of characters ready in RX Fifo */

But what does it return? The number of available characters? Please
make the comment more specific.

> +static int pic32_uart_pending_input(void __iomem *base)
> +{
> +       /* check if rx buffer overrun error has occurred */
> +       if (readl(base + U_STA) & UART_RX_OERR) {
> +               readl(base + U_RXR);
> +
> +               /* clear OERR to keep receiving */
> +               writel(UART_RX_OERR, base + U_STACLR);
> +       }
> +
> +       return readl(base + U_STA) & UART_RX_DATA_AVAIL;
> +}
> +
> +static int pic32_uart_pending(struct udevice *dev, bool input)
> +{
> +       struct pic32_uart_priv *priv = dev_get_priv(dev);
> +
> +       if (input)
> +               return pic32_uart_pending_input(priv->base);

Should return the number of characters available. Should this be?

               return pic32_uart_pending_input(priv->base) ? 1 : 0;

Of course I don't quite know what pic32_uart_pending_input() does, so
I could be wrong.

> +
> +       return !(readl(priv->base + U_STA) & UART_TX_EMPTY);
> +}
> +
> +static int pic32_uart_setbrg(struct udevice *dev, int baudrate)
> +{
> +       struct pic32_uart_priv *priv = dev_get_priv(dev);
> +
> +       return pic32_serial_init(priv->base, priv->uartclk, baudrate);
> +}
> +
> +static int pic32_uart_putc(struct udevice *dev, const char ch)
> +{
> +       struct pic32_uart_priv *priv = dev_get_priv(dev);
> +
> +       /* Check if Tx FIFO is full */
> +       if (readl(priv->base + U_STA) & UART_TX_FULL)
> +               return -EAGAIN;
> +
> +       /* pump the char to tx buffer */
> +       writel(ch, priv->base + U_TXR);
> +
> +       return 0;
> +}
> +
> +static int pic32_uart_getc(struct udevice *dev)
> +{
> +       struct pic32_uart_priv *priv = dev_get_priv(dev);
> +
> +       /* return error if RX fifo is empty */
> +       if (!pic32_uart_pending_input(priv->base))
> +               return -EAGAIN;
> +
> +       /* read the character from rx buffer */
> +       return readl(priv->base + U_RXR) & 0xff;
> +}
> +
> +static int pic32_uart_probe(struct udevice *dev)
> +{
> +       struct pic32_uart_priv *priv = dev_get_priv(dev);
> +       struct udevice *clkdev;
> +       fdt_addr_t addr;
> +       fdt_size_t size;
> +       int ret;
> +
> +       /* get address */
> +       addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg", &size);
> +       if (addr == FDT_ADDR_T_NONE)
> +               return -EINVAL;
> +
> +       priv->base = ioremap(addr, size);
> +       if (!priv->base)
> +               return -EINVAL;
> +
> +       /* get clock rate */
> +       ret = uclass_get_device(UCLASS_CLK, 0, &clkdev);
> +       if (ret) {
> +               printf("clk class not found, %d\n", ret);
> +               return ret;
> +       }
> +       priv->uartclk = clk_get_periph_rate(clkdev, PB2CLK);
> +
> +       /* initialize serial */
> +       return pic32_serial_init(priv->base, priv->uartclk, CONFIG_BAUDRATE);
> +}
> +
> +static const struct dm_serial_ops pic32_uart_ops = {
> +       .putc           = pic32_uart_putc,
> +       .pending        = pic32_uart_pending,
> +       .getc           = pic32_uart_getc,
> +       .setbrg         = pic32_uart_setbrg,
> +};
> +
> +static const struct udevice_id pic32_uart_ids[] = {
> +       { .compatible = "microchip,pic32mzda-uart" },
> +       {}
> +};
> +
> +U_BOOT_DRIVER(pic32_serial) = {
> +       .name           = "pic32-uart",
> +       .id             = UCLASS_SERIAL,
> +       .of_match       = pic32_uart_ids,
> +       .probe          = pic32_uart_probe,
> +       .ops            = &pic32_uart_ops,
> +       .flags          = DM_FLAG_PRE_RELOC,
> +       .priv_auto_alloc_size = sizeof(struct pic32_uart_priv),
> +};
> +
> +#ifdef CONFIG_DEBUG_UART_PIC32
> +#include <debug_uart.h>
> +
> +static inline void _debug_uart_init(void)
> +{
> +       void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE;
> +
> +       pic32_serial_init(base, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
> +}
> +
> +static inline void _debug_uart_putc(int ch)

> +{
> +       writel(ch, CONFIG_DEBUG_UART_BASE + U_TXR);
> +}
> +
> +DEBUG_UART_FUNCS
> +#endif
> --
> 1.8.3.1
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 04/14] drivers: pinctrl: Add pinctrl driver for Microchip PIC32.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 04/14] drivers: pinctrl: Add pinctrl driver for Microchip PIC32 Purna Chandra Mandal
  2016-01-13 13:42   ` Daniel Schwierzeck
  2016-01-13 14:55   ` Tom Rini
@ 2016-01-13 20:10   ` Simon Glass
  2 siblings, 0 replies; 62+ messages in thread
From: Simon Glass @ 2016-01-13 20:10 UTC (permalink / raw)
  To: u-boot

On 12 January 2016 at 03:18, Purna Chandra Mandal
<purna.mandal@microchip.com> wrote:
> In PIC32 pin-controller is a combined gpio-controller, pin-mux and
> pin-config module. Remappable peripherals are assigned pins through
> per-pin based muxing logic. And pin configuration are performed on
> specific port registers which are shared along with gpio controller.
> Note, non-remappable peripherals have default pins assigned thus require
> no muxing.
>
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
>
>
> ---
>
> Changes in v3:
> - read register base from device-tree
> - add/update comments to explain how pinctrl'r works.
> - replace pic32_ioremap() with ioremap().
>
> Changes in v2:
> - add pinconf routine for configuring pin property
>
>  drivers/pinctrl/Kconfig         |   9 +
>  drivers/pinctrl/Makefile        |   1 +
>  drivers/pinctrl/pinctrl_pic32.c | 363 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 373 insertions(+)
>  create mode 100644 drivers/pinctrl/pinctrl_pic32.c

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 05/14] drivers: gpio: add driver for Microchip PIC32 GPIO controller.
  2016-01-12 10:18 ` [U-Boot] [PATCH v3 05/14] drivers: gpio: add driver for Microchip PIC32 GPIO controller Purna Chandra Mandal
  2016-01-13 13:46   ` Daniel Schwierzeck
  2016-01-13 14:55   ` Tom Rini
@ 2016-01-13 20:10   ` Simon Glass
  2016-01-14 10:15     ` Purna Chandra Mandal
  2 siblings, 1 reply; 62+ messages in thread
From: Simon Glass @ 2016-01-13 20:10 UTC (permalink / raw)
  To: u-boot

Hi Puma,

On 12 January 2016 at 03:18, Purna Chandra Mandal
<purna.mandal@microchip.com> wrote:
> In PIC32 GPIO controller is part of PIC32 pin controller.
> PIC32 has ten independently programmable ports and each with multiple pins.
> Each of these pins can be configured and used as GPIO, provided they
> are not in use for other peripherals.
>
> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
>
> ---
>
> Changes in v3:
> - add check on dev_get_addr()
>
> Changes in v2: None
>
>  drivers/gpio/Kconfig      |   7 ++
>  drivers/gpio/Makefile     |   2 +-
>  drivers/gpio/pic32_gpio.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 183 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpio/pic32_gpio.c
>

Reviewed-by: Simon Glass <sjg@chromium.org>

Just a few nits.

> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index e60e9fd..13e9a6a 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -83,4 +83,11 @@ config VYBRID_GPIO
>         help
>           Say yes here to support Vybrid vf610 GPIOs.
>
> +config PIC32_GPIO
> +       bool "Microchip PIC32 GPIO driver"
> +       depends on DM_GPIO
> +       default y if MACH_PIC32
> +       help
> +         Say yes here to support Microchip PIC32 GPIOs.
> +
>  endmenu
> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> index fb4fd25..845a6d4 100644
> --- a/drivers/gpio/Makefile
> +++ b/drivers/gpio/Makefile
> @@ -46,4 +46,4 @@ obj-$(CONFIG_STM32_GPIO)      += stm32_gpio.o
>  obj-$(CONFIG_ZYNQ_GPIO)                += zynq_gpio.o
>  obj-$(CONFIG_VYBRID_GPIO)      += vybrid_gpio.o
>  obj-$(CONFIG_HIKEY_GPIO)       += hi6220_gpio.o
> -
> +obj-$(CONFIG_PIC32_GPIO)       += pic32_gpio.o
> diff --git a/drivers/gpio/pic32_gpio.c b/drivers/gpio/pic32_gpio.c
> new file mode 100644
> index 0000000..5b23af4
> --- /dev/null
> +++ b/drivers/gpio/pic32_gpio.c
> @@ -0,0 +1,175 @@
> +/*
> + * Copyright (c) 2015 Microchip Technology Inc
> + * Purna Chandra Mandal <purna.mandal@microchip.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <malloc.h>
> +#include <asm/io.h>
> +#include <asm/gpio.h>
> +#include <linux/compat.h>
> +#include <dt-bindings/gpio/gpio.h>
> +#include <mach/pic32.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* Peripheral Pin Control */
> +struct pic32_reg_port {
> +       struct pic32_reg_atomic ansel;
> +       struct pic32_reg_atomic tris;
> +       struct pic32_reg_atomic port;
> +       struct pic32_reg_atomic lat;
> +       struct pic32_reg_atomic open_drain;
> +       struct pic32_reg_atomic cnpu;
> +       struct pic32_reg_atomic cnpd;
> +       struct pic32_reg_atomic cncon;
> +};
> +
> +enum {
> +       MICROCHIP_GPIO_DIR_OUT,
> +       MICROCHIP_GPIO_DIR_IN,
> +       MICROCHIP_GPIOS_PER_BANK = 16,
> +};
> +
> +struct pic32_gpio_priv {
> +       struct pic32_reg_port *regs;
> +       char name[2];
> +};
> +
> +static int pic32_gpio_get_value(struct udevice *dev, unsigned offset)
> +{
> +       struct pic32_gpio_priv *priv = dev_get_priv(dev);
> +
> +       return !!(readl(&priv->regs->port.raw) & BIT(offset));
> +}
> +
> +static int pic32_gpio_set_value(struct udevice *dev, unsigned offset,
> +                               int value)
> +{
> +       struct pic32_gpio_priv *priv = dev_get_priv(dev);
> +       int mask = BIT(offset);
> +
> +       if (value)
> +               writel(mask, &priv->regs->port.set);
> +       else
> +               writel(mask, &priv->regs->port.clr);
> +
> +       return 0;
> +}
> +
> +static int pic32_gpio_direction(struct udevice *dev, unsigned offset)
> +{
> +       struct pic32_gpio_priv *priv = dev_get_priv(dev);
> +
> +       if (readl(&priv->regs->ansel.raw) & BIT(offset))
> +               return -1;

What does this error mean? Should it be -EPERM? Perhaps add a comment.

> +
> +       if (readl(&priv->regs->tris.raw) & BIT(offset))
> +               return MICROCHIP_GPIO_DIR_IN;
> +       else
> +               return MICROCHIP_GPIO_DIR_OUT;
> +}
> +
> +static int pic32_gpio_direction_input(struct udevice *dev, unsigned offset)
> +{
> +       struct pic32_gpio_priv *priv = dev_get_priv(dev);
> +       int mask = BIT(offset);
> +
> +       writel(mask, &priv->regs->ansel.clr);
> +       writel(mask, &priv->regs->tris.set);
> +
> +       return 0;
> +}
> +
> +static int pic32_gpio_direction_output(struct udevice *dev,
> +                                      unsigned offset, int value)
> +{
> +       struct pic32_gpio_priv *priv = dev_get_priv(dev);
> +       int mask = BIT(offset);
> +
> +       writel(mask, &priv->regs->ansel.clr);
> +       writel(mask, &priv->regs->tris.clr);
> +
> +       pic32_gpio_set_value(dev, offset, value);
> +       return 0;
> +}
> +
> +static int pic32_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
> +                           struct fdtdec_phandle_args *args)
> +{
> +       desc->offset = args->args[0];

This is done automatically in gpio_find_and_xlate(), so you shouldn't need it.

> +       desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
> +
> +       return 0;
> +}
> +
> +static int pic32_gpio_get_function(struct udevice *dev, unsigned offset)
> +{
> +       int ret = GPIOF_UNUSED;
> +
> +       switch (pic32_gpio_direction(dev, offset)) {
> +       case MICROCHIP_GPIO_DIR_OUT:
> +               ret = GPIOF_OUTPUT;
> +               break;
> +       case MICROCHIP_GPIO_DIR_IN:
> +               ret = GPIOF_INPUT;
> +               break;
> +       default:
> +               ret = GPIOF_UNUSED;
> +               break;
> +       }
> +       return ret;
> +}
> +
> +static const struct dm_gpio_ops gpio_pic32_ops = {
> +       .direction_input        = pic32_gpio_direction_input,
> +       .direction_output       = pic32_gpio_direction_output,
> +       .get_value              = pic32_gpio_get_value,
> +       .set_value              = pic32_gpio_set_value,
> +       .get_function           = pic32_gpio_get_function,
> +       .xlate                  = pic32_gpio_xlate,
> +};
> +
> +static int pic32_gpio_probe(struct udevice *dev)
> +{
> +       struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
> +       struct pic32_gpio_priv *priv = dev_get_priv(dev);
> +       fdt_addr_t addr;
> +       fdt_size_t size;
> +       char *end;
> +       int bank;
> +
> +       addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg", &size);
> +       if (addr == FDT_ADDR_T_NONE)
> +               return -EINVAL;
> +
> +       priv->regs = ioremap(addr, size);
> +       if (!priv->regs)
> +               return -EINVAL;
> +
> +       uc_priv->gpio_count = MICROCHIP_GPIOS_PER_BANK;
> +       end = strrchr(dev->name, '@');
> +       bank = trailing_strtoln(dev->name, end);
> +       priv->name[0] = 'A' + bank;
> +       uc_priv->bank_name = priv->name;
> +
> +       return 0;
> +}
> +
> +static const struct udevice_id pic32_gpio_ids[] = {
> +       { .compatible = "microchip,pic32mzda-gpio" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(gpio_pic32) = {
> +       .name           = "gpio_pic32",
> +       .id             = UCLASS_GPIO,
> +       .of_match       = pic32_gpio_ids,
> +       .ops            = &gpio_pic32_ops,
> +       .probe          = pic32_gpio_probe,
> +       .priv_auto_alloc_size   = sizeof(struct pic32_gpio_priv),
> +};
> --
> 1.8.3.1
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 01/14] MIPS: initialize board_init_f() argument to zero.
  2016-01-12 12:29   ` Daniel Schwierzeck
@ 2016-01-14  5:29     ` Purna Chandra Mandal
  2016-01-21 14:06       ` Daniel Schwierzeck
  0 siblings, 1 reply; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-14  5:29 UTC (permalink / raw)
  To: u-boot

On 01/12/2016 05:59 PM, Daniel Schwierzeck wrote:

> 2016-01-12 11:18 GMT+01:00 Purna Chandra Mandal <purna.mandal@microchip.com>:
>> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
>> ---
>>
>> Changes in v3: None
>> Changes in v2: None
>>
>>  arch/mips/cpu/start.S | 2 ++
>>  1 file changed, 2 insertions(+)
>>
>> diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S
>> index e95cdca..35d9650 100644
>> --- a/arch/mips/cpu/start.S
>> +++ b/arch/mips/cpu/start.S
>> @@ -185,6 +185,8 @@ reset:
>>         PTR_ADDU t0, k0, GD_MALLOC_BASE # gd->malloc_base offset
>>         sw      sp, 0(t0)
>>  #endif
>> +       /* Initialize args to zero */
>> +       move    a0, zero
> the comment should be on the same line and more precise. That is
> useful in disassemblies or when debugging. E.g.
>
> move    a0, zero        # a0 <-- boot_flags = 0
>
> Also add a commit message please explaining why the change is
> required. Something like that the boot_flags of board_init_f should be
> set to 0 because $a0 may be utilized in lowlevel_init or
> mips_cache_reset.

ack. Will add accordingly,

>>         PTR_LA  t9, board_init_f
>>         jr      t9
>> --
>> 1.8.3.1
>>
>
>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 03/14] drivers: clk: Add clock driver for Microchip PIC32 Microcontroller.
  2016-01-13 13:38   ` Daniel Schwierzeck
@ 2016-01-14  5:34     ` Purna Chandra Mandal
  0 siblings, 0 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-14  5:34 UTC (permalink / raw)
  To: u-boot

On 01/13/2016 07:08 PM, Daniel Schwierzeck wrote:

> Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra Mandal:
>> PIC32 clock module consists of multiple oscillators, PLLs,
>> mutiplexers
>> and dividers capable of supplying clock to various controllers
>> on or off-chip.
>>
>> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
>> Reviewed-by: Simon Glass <sjg@chromium.org>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
>
> nits below
>
>> ---
>>
>> Changes in v3:
>> - rename clk-pic32.c to clk_pic32.c
>> - update clock binding documentation
>> - replace pic32_ioremap() with ioremap()
>> - separate MPLL initialization constants
>>
>> Changes in v2:
>> - add mpll get clock rate
>>
>>  .../clock/microchip,pic32-clock.txt                |  33 ++
>>  drivers/clk/Makefile                               |   1 +
>>  drivers/clk/clk_pic32.c                            | 433
>> +++++++++++++++++++++
>>  include/dt-bindings/clock/microchip,clock.h        |  29 ++
>>  4 files changed, 496 insertions(+)
>>  create mode 100644 doc/device-tree-bindings/clock/microchip,pic32
>> -clock.txt
>>  create mode 100644 drivers/clk/clk_pic32.c
>>  create mode 100644 include/dt-bindings/clock/microchip,clock.h
>>
>> diff --git a/doc/device-tree-bindings/clock/microchip,pic32-clock.txt
>> b/doc/device-tree-bindings/clock/microchip,pic32-clock.txt
>> new file mode 100644
>> index 0000000..02e5ce4
>> --- /dev/null
>> +++ b/doc/device-tree-bindings/clock/microchip,pic32-clock.txt
>> @@ -0,0 +1,33 @@
>> +* Microchip PIC32 Clock and Oscillator
>> +
>> +Microchip PIC32 clock tree consists of few oscillators, PLLs,
>> +multiplexers and few divider modules capable of supplying clocks
>> +to various controllers within SoC and also to off-chip.
>> +
>> +PIC32 clock controller output is defined by indices as defined
>> +in [0]
>> +
>> +[0] include/dt-bindings/clock/microchip,clock.h
>> +
>> +Required Properties:
>> +- compatible: should be "microchip,pic32mzda_clk"
>> +- reg: physical base address of the controller and length of memory
>> mapped
>> +       region.
>> +- #clock-cells: should be 1.
>> +
>> +Example: Clock controller node:
>> +
>> +	clock: clk at 1f801200 {
>> +		compatible = "microchip,pic32mzda_clk";
>> +		reg = <0x1f801200 0x1000>;
>> +	};
>> +
>> +Example: UART controller node that consumes the clock generated by
>> the clock
>> +controller:
>> +
>> +	uart1: serial at 1f822000 {
>> +		compatible = "microchip,pic32mzda-uart";
>> +		reg = <0xbf822000 0x50>;
>> +		interrupts = <112 IRQ_TYPE_LEVEL_HIGH>;
>> +		clocks = <&clock PB2CLK>;
>> +	};
>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> index 4a6a4a8..adda769 100644
>> --- a/drivers/clk/Makefile
>> +++ b/drivers/clk/Makefile
>> @@ -9,3 +9,4 @@ obj-$(CONFIG_CLK) += clk-uclass.o
>>  obj-$(CONFIG_ROCKCHIP_RK3036) += clk_rk3036.o
>>  obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o
>>  obj-$(CONFIG_SANDBOX) += clk_sandbox.o
>> +obj-$(CONFIG_MACH_PIC32) += clk_pic32.o
>> diff --git a/drivers/clk/clk_pic32.c b/drivers/clk/clk_pic32.c
>> new file mode 100644
>> index 0000000..bb0a1cf
>> --- /dev/null
>> +++ b/drivers/clk/clk_pic32.c
>> @@ -0,0 +1,433 @@
>> +/*
>> + * Copyright (C) 2015 Purna Chandra Mandal <
>> purna.mandal at microchip.com>
>> + *
>> + * SPDX-License-Identifier:	GPL-2.0+
>> + *
>> + */
>> +
>> [...]
>> +
>> +static ulong pic32_set_periph_rate(struct udevice *dev, int periph,
>> ulong rate)
>> +{
>> +	struct pic32_clk_priv *priv = dev_get_priv(dev);
>> +	ulong pll_hz;
>> +
>> +	switch (periph) {
>> +	case REF1CLK ... REF5CLK:
>> +		pll_hz = pic32_get_pll_rate(priv);
>> +		pic32_set_refclk(priv, periph, pll_hz, rate,
>> ROCLK_SRC_SPLL);
>> +		break;
>> +	default:
>> +		break;
>> +	}
>> +
>> +	return rate;
>> +}
>> +
>> +static struct clk_ops pic32_pic32_clk_ops = {
>> +	.get_rate = pic32_clk_get_rate,
>> +	.set_periph_rate = pic32_set_periph_rate,
>> +	.get_periph_rate = pic32_get_periph_rate,
>> +};
>> +
>> +static int pic32_clk_probe(struct udevice *dev)
>> +{
>> +	struct pic32_clk_priv *priv = dev_get_priv(dev);
>> +	fdt_addr_t addr;
>> +	fdt_size_t size;
>> +
>> +	addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset,
>> "reg", &size);
>> +	if (addr == FDT_ADDR_T_NONE)
>> +		return -EINVAL;
>> +
>> +	priv->iobase = ioremap(addr, size);
>> +	if (!priv->iobase)
>> +		return -EINVAL;
> you can drop this check. ioremap() always returns a mapped address

ack. Will drop.

>> +
>> +	priv->syscfg_base = pic32_get_syscfg_base();
>> +
>> +	/* initialize clocks */
>> +	pic32_clk_init(dev);
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct udevice_id pic32_clk_ids[] = {
>> +	{ .compatible = "microchip,pic32mzda_clk"},
>> +	{}
>> +};
>> +
>> +U_BOOT_DRIVER(pic32_clk) = {
>> +	.name		= "pic32_clk",
>> +	.id		= UCLASS_CLK,
>> +	.of_match	= pic32_clk_ids,
>> +	.flags		= DM_FLAG_PRE_RELOC,
>> +	.ops		= &pic32_pic32_clk_ops,
>> +	.probe		= pic32_clk_probe,
>> +	.priv_auto_alloc_size = sizeof(struct pic32_clk_priv),
>> +};
>> diff --git a/include/dt-bindings/clock/microchip,clock.h b/include/dt
>> -bindings/clock/microchip,clock.h
>> new file mode 100644
>> index 0000000..93c222d
>> --- /dev/null
>> +++ b/include/dt-bindings/clock/microchip,clock.h
>> @@ -0,0 +1,29 @@
>> +/*
>> + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
>> + *
>> + * SPDX-License-Identifier:	GPL-2.0+
>> + *
>> + */
>> +
>> +#ifndef __CLK_MICROCHIP_PIC32
>> +#define __CLK_MICROCHIP_PIC32
>> +
>> +/* clock output indices */
>> +#define BASECLK	0
>> +#define PLLCLK	1
>> +#define MPLL	2
>> +#define SYSCLK	3
>> +#define PB1CLK	4
>> +#define PB2CLK	5
>> +#define PB3CLK	6
>> +#define PB4CLK	7
>> +#define PB5CLK	8
>> +#define PB6CLK	9
>> +#define PB7CLK	10
>> +#define REF1CLK	11
>> +#define REF2CLK	12
>> +#define REF3CLK	13
>> +#define REF4CLK	14
>> +#define REF5CLK	15
>> +
>> +#endif	/* __CLK_MICROCHIP_PIC32 */

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 05/14] drivers: gpio: add driver for Microchip PIC32 GPIO controller.
  2016-01-13 14:08     ` Daniel Schwierzeck
@ 2016-01-14  5:41       ` Purna Chandra Mandal
  0 siblings, 0 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-14  5:41 UTC (permalink / raw)
  To: u-boot

On 01/13/2016 07:38 PM, Daniel Schwierzeck wrote:

> Am Mittwoch, den 13.01.2016, 14:46 +0100 schrieb Daniel Schwierzeck:
>> Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra
>> Mandal:
>>> In PIC32 GPIO controller is part of PIC32 pin controller.
>>> PIC32 has ten independently programmable ports and each with
>>> multiple
>>> pins.
>>> Each of these pins can be configured and used as GPIO, provided
>>> they
>>> are not in use for other peripherals.
>>>
>>> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
>> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
>>
>> nits below
>>
>>> ---
>>>
>>> Changes in v3:
>>> - add check on dev_get_addr()
>>>
>>> Changes in v2: None
>>>
>>>  drivers/gpio/Kconfig      |   7 ++
>>>  drivers/gpio/Makefile     |   2 +-
>>>  drivers/gpio/pic32_gpio.c | 175
>>> ++++++++++++++++++++++++++++++++++++++++++++++
>>>  3 files changed, 183 insertions(+), 1 deletion(-)
>>>  create mode 100644 drivers/gpio/pic32_gpio.c
>>>
>>> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
>>> index e60e9fd..13e9a6a 100644
>>> --- a/drivers/gpio/Kconfig
>>> +++ b/drivers/gpio/Kconfig
>>> @@ -83,4 +83,11 @@ config VYBRID_GPIO
>>>  	help
>>>  	  Say yes here to support Vybrid vf610 GPIOs.
>>>  
>>> +config PIC32_GPIO
>>> +	bool "Microchip PIC32 GPIO driver"
>>> +	depends on DM_GPIO
>>> +	default y if MACH_PIC32
> this should be
>
> depends on DM_GPIO && MACH_PIC32

ack, will add.

>>> +	help
>>> +	  Say yes here to support Microchip PIC32 GPIOs.
>>> +
>>>  endmenu
>>> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
>>> index fb4fd25..845a6d4 100644
>>> --- a/drivers/gpio/Makefile
>>> +++ b/drivers/gpio/Makefile
>>> @@ -46,4 +46,4 @@ obj-$(CONFIG_STM32_GPIO)	+= stm32_gpio.o
>>>  obj-$(CONFIG_ZYNQ_GPIO)		+= zynq_gpio.o
>>>  obj-$(CONFIG_VYBRID_GPIO)	+= vybrid_gpio.o
>>>  obj-$(CONFIG_HIKEY_GPIO)	+= hi6220_gpio.o
>>> -
>>> +obj-$(CONFIG_PIC32_GPIO)	+= pic32_gpio.o
>>> diff --git a/drivers/gpio/pic32_gpio.c b/drivers/gpio/pic32_gpio.c
>>> new file mode 100644
>>> index 0000000..5b23af4
>>> --- /dev/null
>>> +++ b/drivers/gpio/pic32_gpio.c
>>> @@ -0,0 +1,175 @@
>>> +/*
>>> + * Copyright (c) 2015 Microchip Technology Inc
>>> + * Purna Chandra Mandal <purna.mandal@microchip.com>
>>> + *
>>> + * SPDX-License-Identifier:	GPL-2.0+
>>> + */
>>> +
>>> +#include <common.h>
>>> +#include <dm.h>
>>> +#include <errno.h>
>>> +#include <malloc.h>
>>> +#include <asm/io.h>
>>> +#include <asm/gpio.h>
>>> +#include <linux/compat.h>
>>> +#include <dt-bindings/gpio/gpio.h>
>>> +#include <mach/pic32.h>
>>> +
>>> +DECLARE_GLOBAL_DATA_PTR;
>>> +
>>> +/* Peripheral Pin Control */
>>> +struct pic32_reg_port {
>>> +	struct pic32_reg_atomic ansel;
>>> +	struct pic32_reg_atomic tris;
>>> +	struct pic32_reg_atomic port;
>>> +	struct pic32_reg_atomic lat;
>>> +	struct pic32_reg_atomic open_drain;
>>> +	struct pic32_reg_atomic cnpu;
>>> +	struct pic32_reg_atomic cnpd;
>>> +	struct pic32_reg_atomic cncon;
>>> +};
>>> +
>>> +enum {
>>> +	MICROCHIP_GPIO_DIR_OUT,
>>> +	MICROCHIP_GPIO_DIR_IN,
>>> +	MICROCHIP_GPIOS_PER_BANK = 16,
>>> +};
>>> +
>>> +struct pic32_gpio_priv {
>>> +	struct pic32_reg_port *regs;
>>> +	char name[2];
>>> +};
>>> +
>>> +static int pic32_gpio_get_value(struct udevice *dev, unsigned
>>> offset)
>>> +{
>>> +	struct pic32_gpio_priv *priv = dev_get_priv(dev);
>>> +
>>> +	return !!(readl(&priv->regs->port.raw) & BIT(offset));
>>> +}
>>> +
>>> +static int pic32_gpio_set_value(struct udevice *dev, unsigned
>>> offset,
>>> +				int value)
>>> +{
>>> +	struct pic32_gpio_priv *priv = dev_get_priv(dev);
>>> +	int mask = BIT(offset);
>>> +
>>> +	if (value)
>>> +		writel(mask, &priv->regs->port.set);
>>> +	else
>>> +		writel(mask, &priv->regs->port.clr);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int pic32_gpio_direction(struct udevice *dev, unsigned
>>> offset)
>>> +{
>>> +	struct pic32_gpio_priv *priv = dev_get_priv(dev);
>>> +
>>> +	if (readl(&priv->regs->ansel.raw) & BIT(offset))
>>> +		return -1;
>>> +
>>> +	if (readl(&priv->regs->tris.raw) & BIT(offset))
>>> +		return MICROCHIP_GPIO_DIR_IN;
>>> +	else
>>> +		return MICROCHIP_GPIO_DIR_OUT;
>>> +}
>>> +
>>> +static int pic32_gpio_direction_input(struct udevice *dev,
>>> unsigned
>>> offset)
>>> +{
>>> +	struct pic32_gpio_priv *priv = dev_get_priv(dev);
>>> +	int mask = BIT(offset);
>>> +
>>> +	writel(mask, &priv->regs->ansel.clr);
>>> +	writel(mask, &priv->regs->tris.set);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int pic32_gpio_direction_output(struct udevice *dev,
>>> +				       unsigned offset, int value)
>>> +{
>>> +	struct pic32_gpio_priv *priv = dev_get_priv(dev);
>>> +	int mask = BIT(offset);
>>> +
>>> +	writel(mask, &priv->regs->ansel.clr);
>>> +	writel(mask, &priv->regs->tris.clr);
>>> +
>>> +	pic32_gpio_set_value(dev, offset, value);
>>> +	return 0;
>>> +}
>>> +
>>> +static int pic32_gpio_xlate(struct udevice *dev, struct gpio_desc
>>> *desc,
>>> +			    struct fdtdec_phandle_args *args)
>>> +{
>>> +	desc->offset = args->args[0];
>>> +	desc->flags = args->args[1] & GPIO_ACTIVE_LOW ?
>>> GPIOD_ACTIVE_LOW : 0;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int pic32_gpio_get_function(struct udevice *dev, unsigned
>>> offset)
>>> +{
>>> +	int ret = GPIOF_UNUSED;
>>> +
>>> +	switch (pic32_gpio_direction(dev, offset)) {
>>> +	case MICROCHIP_GPIO_DIR_OUT:
>>> +		ret = GPIOF_OUTPUT;
>>> +		break;
>>> +	case MICROCHIP_GPIO_DIR_IN:
>>> +		ret = GPIOF_INPUT;
>>> +		break;
>>> +	default:
>>> +		ret = GPIOF_UNUSED;
>>> +		break;
>>> +	}
>>> +	return ret;
>>> +}
>>> +
>>> +static const struct dm_gpio_ops gpio_pic32_ops = {
>>> +	.direction_input	= pic32_gpio_direction_input,
>>> +	.direction_output	= pic32_gpio_direction_output,
>>> +	.get_value		= pic32_gpio_get_value,
>>> +	.set_value		= pic32_gpio_set_value,
>>> +	.get_function		= pic32_gpio_get_function,
>>> +	.xlate			= pic32_gpio_xlate,
>>> +};
>>> +
>>> +static int pic32_gpio_probe(struct udevice *dev)
>>> +{
>>> +	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
>>> +	struct pic32_gpio_priv *priv = dev_get_priv(dev);
>>> +	fdt_addr_t addr;
>>> +	fdt_size_t size;
>>> +	char *end;
>>> +	int bank;
>>> +
>>> +	addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset,
>>> "reg", &size);
>>> +	if (addr == FDT_ADDR_T_NONE)
>>> +		return -EINVAL;
>>> +
>>> +	priv->regs = ioremap(addr, size);
>>> +	if (!priv->regs)
>>> +		return -EINVAL;
>> you can drop this check. ioremap() always returns a mapped address.

ack. will drop.

>>> +
>>> +	uc_priv->gpio_count = MICROCHIP_GPIOS_PER_BANK;
>>> +	end = strrchr(dev->name, '@');
>>> +	bank = trailing_strtoln(dev->name, end);
>>> +	priv->name[0] = 'A' + bank;
>>> +	uc_priv->bank_name = priv->name;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static const struct udevice_id pic32_gpio_ids[] = {
>>> +	{ .compatible = "microchip,pic32mzda-gpio" },
>>> +	{ }
>>> +};
>>> +
>>> +U_BOOT_DRIVER(gpio_pic32) = {
>>> +	.name		= "gpio_pic32",
>>> +	.id		= UCLASS_GPIO,
>>> +	.of_match	= pic32_gpio_ids,
>>> +	.ops		= &gpio_pic32_ops,
>>> +	.probe		= pic32_gpio_probe,
>>> +	.priv_auto_alloc_size	= sizeof(struct
>>> pic32_gpio_priv),
>>> +};

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 06/14] drivers: serial: add driver for Microchip PIC32 UART controller.
  2016-01-13 14:03     ` Daniel Schwierzeck
@ 2016-01-14  5:42       ` Purna Chandra Mandal
  0 siblings, 0 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-14  5:42 UTC (permalink / raw)
  To: u-boot

On 01/13/2016 07:33 PM, Daniel Schwierzeck wrote:

> Am Mittwoch, den 13.01.2016, 14:49 +0100 schrieb Daniel Schwierzeck:
>> Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra
>> Mandal:
>>> From: Paul Thacker <paul.thacker@microchip.com>
>>>
>>> This adds PIC32 UART controller support based on driver model.
>>>
>>> Signed-off-by: Paul Thacker <paul.thacker@microchip.com>
>>> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
>>>
>> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
>>
>> nits below
> I forgot one thing
>>> ---
>>>
>>> Changes in v3:
>>> - remove ofdata_to_platdata, and replace platdata with priv
>>> - remove special handling of '\r' as being handled by serial-uclass
>>> - remove loop to wait for space in tx buffer before pumping char
>>>
>>> Changes in v2:
>>> - fix missing/corrupted chars during baud rate change
>>> - remove loop until any char is avaialbale in getc()
>>>
>>>  .../serial/microchip,pic32-uart.txt                |   5 +
>>>  drivers/serial/Kconfig                             |  13 ++
>>>  drivers/serial/Makefile                            |   1 +
>>>  drivers/serial/serial_pic32.c                      | 199
>>> +++++++++++++++++++++
>>>  4 files changed, 218 insertions(+)
>>>  create mode 100644 doc/device-tree-bindings/serial/microchip,pic32
>>> -uart.txt
>>>  create mode 100644 drivers/serial/serial_pic32.c
>>>
>>> diff --git a/doc/device-tree-bindings/serial/microchip,pic32
>>> -uart.txt
>>> b/doc/device-tree-bindings/serial/microchip,pic32-uart.txt
>>> new file mode 100644
>>> index 0000000..f00e215
>>> --- /dev/null
>>> +++ b/doc/device-tree-bindings/serial/microchip,pic32-uart.txt
>>> @@ -0,0 +1,5 @@
>>> +* Microchip PIC32 serial UART
>>> +
>>> +Required properties:
>>> +- compatible: must be "microchip,pic32mzda-uart".
>>> +- reg: exactly one register range.
>>> diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
>>> index 1fc287e..9763ea1 100644
>>> --- a/drivers/serial/Kconfig
>>> +++ b/drivers/serial/Kconfig
>>> @@ -107,6 +107,14 @@ config DEBUG_UART_APBUART
>>>  	  will need to provide parameters to make this work. The
>>> driver will
>>>  	  be available until the real driver model serial is
>>> running.
>>>  
>>> +config DEBUG_UART_PIC32
>>> +	bool "Microchip PIC32"
>>> +	help
>>> +	  Select this to enable a debug UART using the
>>> serial_pic32
>>> driver. You
>>> +	  will need to provide parameters to make this work. The
>>> driver will
>>> +	  be available until the real driver model serial is
>>> running.
>>> +
>>> +
>>>  endchoice
>>>  
>>>  config DEBUG_UART_BASE
>>> @@ -223,4 +231,9 @@ config UNIPHIER_SERIAL
>>>  	  If you have a UniPhier based board and want to use the
>>> on
>>> -chip
>>>  	  serial ports, say Y to this option. If unsure, say N.
>>>  
>>> +config PIC32_SERIAL
>>> +	bool "Support for Microchip PIC32 on-chip UART"
> you should add
>
> depends on DM_SERIAL && MACH_PIC32

ack. Will add.

>>> +	help
>>> +	  Support for the UART found on Microchip PIC32 SoC's.
>>> +
>>>  endmenu
>>> diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
>>> index dd87147..57cd38b 100644
>>> --- a/drivers/serial/Makefile
>>> +++ b/drivers/serial/Makefile
>>> @@ -41,6 +41,7 @@ obj-$(CONFIG_MXS_AUART) += mxs_auart.o
>>>  obj-$(CONFIG_ARC_SERIAL) += serial_arc.o
>>>  obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o
>>>  obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o
>>> +obj-$(CONFIG_PIC32_SERIAL) += serial_pic32.o
>>>  
>>>  ifndef CONFIG_SPL_BUILD
>>>  obj-$(CONFIG_USB_TTY) += usbtty.o
>>> diff --git a/drivers/serial/serial_pic32.c
>>> b/drivers/serial/serial_pic32.c
>>> new file mode 100644
>>> index 0000000..ee9d056
>>> --- /dev/null
>>> +++ b/drivers/serial/serial_pic32.c
>>> @@ -0,0 +1,199 @@
>>> +/*
>>> + * (c) 2015 Paul Thacker <paul.thacker@microchip.com>
>>> + *
>>> + * SPDX-License-Identifier:	GPL-2.0+
>>> + *
>>> + */
>>> +#include <common.h>
>>> +#include <clk.h>
>>> +#include <dm.h>
>>> +#include <serial.h>
>>> +#include <wait_bit.h>
>>> +#include <mach/pic32.h>
>>> +#include <dt-bindings/clock/microchip,clock.h>
>>> +
>>> +DECLARE_GLOBAL_DATA_PTR;
>>> +
>>> +/* UART Control Registers */
>>> +#define U_MOD		0x00
>>> +#define U_MODCLR	(U_MOD + _CLR_OFFSET)
>>> +#define U_MODSET	(U_MOD + _SET_OFFSET)
>>> +#define U_STA		0x10
>>> +#define U_STACLR	(U_STA + _CLR_OFFSET)
>>> +#define U_STASET	(U_STA + _SET_OFFSET)
>>> +#define U_TXR		0x20
>>> +#define U_RXR		0x30
>>> +#define U_BRG		0x40
>>> +
>>> +/* U_MOD bits */
>>> +#define UART_ENABLE		BIT(15)
>>> +
>>> +/* U_STA bits */
>>> +#define UART_RX_ENABLE		BIT(12)
>>> +#define UART_TX_BRK		BIT(11)
>>> +#define UART_TX_ENABLE		BIT(10)
>>> +#define UART_TX_FULL		BIT(9)
>>> +#define UART_TX_EMPTY		BIT(8)
>>> +#define UART_RX_OERR		BIT(1)
>>> +#define UART_RX_DATA_AVAIL	BIT(0)
>>> +
>>> +struct pic32_uart_priv {
>>> +	void __iomem *base;
>>> +	ulong uartclk;
>>> +};
>>> +
>>> +/*
>>> + * Initialize the serial port with the given baudrate.
>>> + * The settings are always 8 data bits, no parity, 1 stop bit, no
>>> start bits.
>>> + */
>>> +static int pic32_serial_init(void __iomem *base, ulong clk, u32
>>> baudrate)
>>> +{
>>> +	u32 div = DIV_ROUND_CLOSEST(clk, baudrate * 16);
>>> +
>>> +	/* wait for TX FIFO to empty */
>>> +	wait_for_bit(__func__, base + U_STA, UART_TX_EMPTY,
>>> +		     true, CONFIG_SYS_HZ, false);
>>> +
>>> +	/* send break */
>>> +	writel(UART_TX_BRK, base + U_STASET);
>>> +
>>> +	/* disable and clear mode */
>>> +	writel(0, base + U_MOD);
>>> +	writel(0, base + U_STA);
>>> +
>>> +	/* set baud rate generator */
>>> +	writel(div - 1, base + U_BRG);
>>> +
>>> +	/* enable the UART for TX and RX */
>>> +	writel(UART_TX_ENABLE | UART_RX_ENABLE, base + U_STASET);
>>> +
>>> +	/* enable the UART */
>>> +	writel(UART_ENABLE, base + U_MODSET);
>>> +	return 0;
>>> +}
>>> +
>>> +/* Check number of characters ready in RX Fifo */
>>> +static int pic32_uart_pending_input(void __iomem *base)
>>> +{
>>> +	/* check if rx buffer overrun error has occurred */
>>> +	if (readl(base + U_STA) & UART_RX_OERR) {
>>> +		readl(base + U_RXR);
>>> +
>>> +		/* clear OERR to keep receiving */
>>> +		writel(UART_RX_OERR, base + U_STACLR);
>>> +	}
>>> +
>>> +	return readl(base + U_STA) & UART_RX_DATA_AVAIL;
>>> +}
>>> +
>>> +static int pic32_uart_pending(struct udevice *dev, bool input)
>>> +{
>>> +	struct pic32_uart_priv *priv = dev_get_priv(dev);
>>> +
>>> +	if (input)
>>> +		return pic32_uart_pending_input(priv->base);
>>> +
>>> +	return !(readl(priv->base + U_STA) & UART_TX_EMPTY);
>>> +}
>>> +
>>> +static int pic32_uart_setbrg(struct udevice *dev, int baudrate)
>>> +{
>>> +	struct pic32_uart_priv *priv = dev_get_priv(dev);
>>> +
>>> +	return pic32_serial_init(priv->base, priv->uartclk,
>>> baudrate);
>>> +}
>>> +
>>> +static int pic32_uart_putc(struct udevice *dev, const char ch)
>>> +{
>>> +	struct pic32_uart_priv *priv = dev_get_priv(dev);
>>> +
>>> +	/* Check if Tx FIFO is full */
>>> +	if (readl(priv->base + U_STA) & UART_TX_FULL)
>>> +		return -EAGAIN;
>>> +
>>> +	/* pump the char to tx buffer */
>>> +	writel(ch, priv->base + U_TXR);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int pic32_uart_getc(struct udevice *dev)
>>> +{
>>> +	struct pic32_uart_priv *priv = dev_get_priv(dev);
>>> +
>>> +	/* return error if RX fifo is empty */
>>> +	if (!pic32_uart_pending_input(priv->base))
>>> +		return -EAGAIN;
>>> +
>>> +	/* read the character from rx buffer */
>>> +	return readl(priv->base + U_RXR) & 0xff;
>>> +}
>>> +
>>> +static int pic32_uart_probe(struct udevice *dev)
>>> +{
>>> +	struct pic32_uart_priv *priv = dev_get_priv(dev);
>>> +	struct udevice *clkdev;
>>> +	fdt_addr_t addr;
>>> +	fdt_size_t size;
>>> +	int ret;
>>> +
>>> +	/* get address */
>>> +	addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset,
>>> "reg", &size);
>>> +	if (addr == FDT_ADDR_T_NONE)
>>> +		return -EINVAL;
>>> +
>>> +	priv->base = ioremap(addr, size);
>>> +	if (!priv->base)
>>> +		return -EINVAL;
>> you can drop this check. ioremap() always returns a mapped address.

ack.

>>> +
>>> +	/* get clock rate */
>>> +	ret = uclass_get_device(UCLASS_CLK, 0, &clkdev);
>>> +	if (ret) {
>>> +		printf("clk class not found, %d\n", ret);
>>> +		return ret;
>>> +	}
>>> +	priv->uartclk = clk_get_periph_rate(clkdev, PB2CLK);
>>> +
>>> +	/* initialize serial */
>>> +	return pic32_serial_init(priv->base, priv->uartclk,
>>> CONFIG_BAUDRATE);
>>> +}
>>> +
>>> +static const struct dm_serial_ops pic32_uart_ops = {
>>> +	.putc		= pic32_uart_putc,
>>> +	.pending	= pic32_uart_pending,
>>> +	.getc		= pic32_uart_getc,
>>> +	.setbrg		= pic32_uart_setbrg,
>>> +};
>>> +
>>> +static const struct udevice_id pic32_uart_ids[] = {
>>> +	{ .compatible = "microchip,pic32mzda-uart" },
>>> +	{}
>>> +};
>>> +
>>> +U_BOOT_DRIVER(pic32_serial) = {
>>> +	.name		= "pic32-uart",
>>> +	.id		= UCLASS_SERIAL,
>>> +	.of_match	= pic32_uart_ids,
>>> +	.probe		= pic32_uart_probe,
>>> +	.ops		= &pic32_uart_ops,
>>> +	.flags		= DM_FLAG_PRE_RELOC,
>>> +	.priv_auto_alloc_size = sizeof(struct pic32_uart_priv),
>>> +};
>>> +
>>> +#ifdef CONFIG_DEBUG_UART_PIC32
>>> +#include <debug_uart.h>
>>> +
>>> +static inline void _debug_uart_init(void)
>>> +{
>>> +	void __iomem *base = (void __iomem
>>> *)CONFIG_DEBUG_UART_BASE;
>>> +
>>> +	pic32_serial_init(base, CONFIG_DEBUG_UART_CLOCK,
>>> CONFIG_BAUDRATE);
>>> +}
>>> +
>>> +static inline void _debug_uart_putc(int ch)
>>> +{
>>> +	writel(ch, CONFIG_DEBUG_UART_BASE + U_TXR);
>>> +}
>>> +
>>> +DEBUG_UART_FUNCS
>>> +#endif

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 08/14] MIPS: Add support for Microchip PIC32MZ[DA] SoC family.
  2016-01-13 14:49   ` Daniel Schwierzeck
@ 2016-01-14  5:54     ` Purna Chandra Mandal
  0 siblings, 0 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-14  5:54 UTC (permalink / raw)
  To: u-boot

On 01/13/2016 08:19 PM, Daniel Schwierzeck wrote:

> Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra Mandal:
>> Add Microchip PIC32MZ[DA] SoC family support.
>>
>> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
>>
>> ---
>>
>> Changes in v3:
>> - drop forcing CONFIG_MIPS_BOOT_* selection in mach-pic32/Kconfig
>> - indent assembly instructions in delay slot
>> - made GPIO-nodes child of pinctrl-node in devicetree
>> - replace pic32_ioremap() with ioremap()
>>
>> Changes in v2:
>> - drop board_early_init_f
>> - use macro LEAF(), END() for lowlevel_init assembly
>> - move initialization of board_init_f() argument to common start.S
>> - move initdram() from board/microchip/ to mach-pic32/cpu.c
>> - remove MIPS virtual address in favor physical one in dts file
>>
>>  arch/mips/dts/pic32mzda.dtsi              | 153
>> ++++++++++++++++++++++++++++++
>>  arch/mips/mach-pic32/Kconfig              |  20 +++-
>>  arch/mips/mach-pic32/Makefile             |   2 +-
>>  arch/mips/mach-pic32/cpu.c                | 147
>> ++++++++++++++++++++++++++++
>>  arch/mips/mach-pic32/include/mach/pic32.h |   3 +
>>  arch/mips/mach-pic32/lowlevel_init.S      |  27 ++++++
>>  arch/mips/mach-pic32/reset.c              |  36 +++++++
>>  7 files changed, 386 insertions(+), 2 deletions(-)
>>  create mode 100644 arch/mips/dts/pic32mzda.dtsi
>>  create mode 100644 arch/mips/mach-pic32/lowlevel_init.S
>>  create mode 100644 arch/mips/mach-pic32/reset.c
>>
>> diff --git a/arch/mips/dts/pic32mzda.dtsi
>> b/arch/mips/dts/pic32mzda.dtsi
>> new file mode 100644
>> index 0000000..fe8b13a
>> --- /dev/null
>> +++ b/arch/mips/dts/pic32mzda.dtsi
>> @@ -0,0 +1,153 @@
>> +/*
>> + * Copyright 2015 Microchip Technology, Inc.
>> + * Purna Chandra Mandal, <purna.mandal@microchip.com>
>> + *
>> + * SPDX-License-Identifier:	GPL-2.0+
>> + */
>> +
>> +#include <dt-bindings/interrupt-controller/irq.h>
>> +#include <dt-bindings/clock/microchip,clock.h>
>> +#include <dt-bindings/gpio/gpio.h>
>> +#include "skeleton.dtsi"
>> +
>> +/ {
>> +	compatible = "microchip,pic32mzda", "microchip,pic32mz";
>> +
>> +	aliases {
>> +		gpio0 = &gpioA;
>> +		gpio1 = &gpioB;
>> +		gpio2 = &gpioC;
>> +		gpio3 = &gpioD;
>> +		gpio4 = &gpioE;
>> +		gpio5 = &gpioF;
>> +		gpio6 = &gpioG;
>> +		gpio7 = &gpioH;
>> +		gpio8 = &gpioJ;
>> +		gpio9 = &gpioK;
>> +	};
>> +
>> +	cpus {
>> +		cpu at 0 {
>> +			compatible = "mips,mips14kc";
>> +		};
>> +	};
>> +
>> +	clock: clk at 1f801200 {
>> +		compatible = "microchip,pic32mzda_clk";
>> +		reg = <0x1f801200 0x1000>;
>> +		clock-cells = <1>;
>> +	};
>> +
>> +	uart1: serial at 1f822000 {
>> +		compatible = "microchip,pic32mzda-uart";
>> +		reg = <0x1f822000 0x50>;
>> +		interrupts = <112 IRQ_TYPE_LEVEL_HIGH>;
>> +		status = "disabled";
>> +		clocks = <&clock PB2CLK>;
>> +	};
>> +
>> +	uart2: serial at 1f822200 {
>> +		compatible = "microchip,pic32mzda-uart";
>> +		reg = <0x1f822200 0x50>;
>> +		interrupts = <145 IRQ_TYPE_LEVEL_HIGH>;
>> +		clocks = <&clock PB2CLK>;
>> +		status = "disabled";
>> +	};
>> +
>> +	uart6: serial at 1f822a00 {
>> +		compatible = "microchip,pic32mzda-uart";
>> +		reg = <0x1f822a00 0x50>;
>> +		interrupts = <188 IRQ_TYPE_LEVEL_HIGH>;
>> +		clocks = <&clock PB2CLK>;
>> +		status = "disabled";
>> +	};
>> +
>> +	evic: interrupt-controller at 1f810000 {
>> +		compatible = "microchip,pic32mzda-evic";
>> +		interrupt-controller;
>> +		#interrupt-cells = <2>;
>> +		reg = <0x1f810000 0x1000>;
>> +	};
>> +
>> +	pinctrl: pinctrl at 1f801400 {
>> +		compatible = "microchip,pic32mzda-pinctrl";
>> +		reg = <0x1f801400 0x100>, /* in  */
>> +		      <0x1f801500 0x200>, /* out */
>> +		      <0x1f860000 0xa00>; /* port */
>> +		reg-names = "ppsin","ppsout","port";
>> +		status = "disabled";
>> +
>> +		ranges = <0 0x1f860000 0xa00>;
>> +		#address-cells = <1>;
>> +		#size-cells = <1>;
>> +		gpioA: gpio0 at 0 {
>> +			compatible = "microchip,pic32mzda-gpio";
>> +			reg = <0x000 0x48>;
>> +			gpio-controller;
>> +			#gpio-cells = <2>;
>> +		};
>> +
>> +		gpioB: gpio1 at 100 {
>> +			compatible = "microchip,pic32mzda-gpio";
>> +			reg = <0x100 0x48>;
>> +			gpio-controller;
>> +			#gpio-cells = <2>;
>> +		};
>> +
>> +		gpioC: gpio2 at 200 {
>> +			compatible = "microchip,pic32mzda-gpio";
>> +			reg = <0x200 0x48>;
>> +			gpio-controller;
>> +			#gpio-cells = <2>;
>> +		};
>> +
>> +		gpioD: gpio3 at 300 {
>> +			compatible = "microchip,pic32mzda-gpio";
>> +			reg = <0x300 0x48>;
>> +			gpio-controller;
>> +			#gpio-cells = <2>;
>> +		};
>> +
>> +		gpioE: gpio4 at 400 {
>> +			compatible = "microchip,pic32mzda-gpio";
>> +			reg = <0x400 0x48>;
>> +			gpio-controller;
>> +			#gpio-cells = <2>;
>> +		};
>> +
>> +		gpioF: gpio5 at 500 {
>> +			compatible = "microchip,pic32mzda-gpio";
>> +			reg = <0x500 0x48>;
>> +			gpio-controller;
>> +			#gpio-cells = <2>;
>> +		};
>> +
>> +		gpioG: gpio6 at 600 {
>> +			compatible = "microchip,pic32mzda-gpio";
>> +			reg = <0x600 0x48>;
>> +			gpio-controller;
>> +			#gpio-cells = <2>;
>> +		};
>> +
>> +		gpioH: gpio7 at 700 {
>> +			compatible = "microchip,pic32mzda-gpio";
>> +			reg = <0x700 0x48>;
>> +			gpio-controller;
>> +			#gpio-cells = <2>;
>> +		};
>> +
>> +		gpioJ: gpio8 at 800 {
>> +			compatible = "microchip,pic32mzda-gpio";
>> +			reg = <0x800 0x48>;
>> +			gpio-controller;
>> +			#gpio-cells = <2>;
>> +		};
>> +
>> +		gpioK: gpio9 at 900 {
>> +			compatible = "microchip,pic32mzda-gpio";
>> +			reg = <0x900 0x48>;
>> +			gpio-controller;
>> +			#gpio-cells = <2>;
>> +		};
>> +	};
>> +};
>> diff --git a/arch/mips/mach-pic32/Kconfig b/arch/mips/mach
>> -pic32/Kconfig
>> index c1cc5e3..74be9fb 100644
>> --- a/arch/mips/mach-pic32/Kconfig
>> +++ b/arch/mips/mach-pic32/Kconfig
>> @@ -2,6 +2,24 @@ menu "Microchip PIC32 platforms"
>>  	depends on MACH_PIC32
>>  
>>  config SYS_SOC
>> -	default "none"
>> +	default "pic32mzda" if SOC_PIC32MZDA
>> +
>> +choice
>> +	prompt "PIC32 SoC select"
>> +
>> +config SOC_PIC32MZDA
>> +	bool "Microchip PIC32MZ[DA] family"
>> +	select SUPPORTS_LITTLE_ENDIAN
>> +	select SUPPORTS_CPU_MIPS32_R1
>> +	select SUPPORTS_CPU_MIPS32_R2
>> +	select MIPS_L1_CACHE_SHIFT_4
>> +	select SYS_MIPS_CACHE_INIT_RAM_LOAD
>> +	select DM_SERIAL
>> +	select PIC32_SERIAL
>> +	select PIC32_PINCTRL
> I think it is better to remove these three options and to select them
> in your board's defconfig. All drivers should have a "depends on
> MACH_PIC32 && DM_XYZ". You could add a "default y" to a driver, if that
> driver is always needed (e.g. serial, gpio, pinctrl, clk). 
>
ack. Will add accordingly,

>> +	help
>> +	  This supports Microchip PIC32MZ[DA] family of
>> microcontrollers.
>> +
>> +endchoice
>>  
>>  endmenu
>> diff --git a/arch/mips/mach-pic32/Makefile b/arch/mips/mach
>> -pic32/Makefile
>> index cb42607..e321e65 100644
>> --- a/arch/mips/mach-pic32/Makefile
>> +++ b/arch/mips/mach-pic32/Makefile
>> @@ -4,4 +4,4 @@
>>  # SPDX-License-Identifier:      GPL-2.0+
>>  #
>>  
>> -obj-y = cpu.o
>> +obj-y = cpu.o lowlevel_init.o reset.o
>> \ No newline at end of file
>> diff --git a/arch/mips/mach-pic32/cpu.c b/arch/mips/mach-pic32/cpu.c
>> index 58fd3ab..8ecdef8 100644
>> --- a/arch/mips/mach-pic32/cpu.c
>> +++ b/arch/mips/mach-pic32/cpu.c
>> @@ -6,8 +6,155 @@
>>   *
>>   */
>>  #include <common.h>
>> +#include <dm.h>
>> +#include <clk.h>
>> +#include <debug_uart.h>
>> +#include <linux/compiler.h>
>> +#include <asm/io.h>
>> +#include <asm/mipsregs.h>
>> +#include <mach/pic32.h>
>> +#include <mach/ddr.h>
>> +#include <dt-bindings/clock/microchip,clock.h>
>>  
>> +/* Flash prefetch */
>> +#define PRECON          0x00
>> +
>> +/* Flash ECCCON */
>> +#define ECC_MASK	0x03
>> +#define ECC_SHIFT	4
>> +
>> +#define CLK_MHZ(x)	((x) / 1000000)
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +static ulong clk_get_cpu_rate(void)
>> +{
>> +	int ret;
>> +	struct udevice *dev;
>> +
>> +	ret = uclass_get_device(UCLASS_CLK, 0, &dev);
>> +	if (ret) {
>> +		panic("uclass-clk: device not found\n");
>> +		return 0;
>> +	}
>> +
>> +	return clk_get_rate(dev);
>> +}
>> +
>> +/* initialize prefetch module related to cpu_clk */
>> +static void prefetch_init(void)
>> +{
>> +	struct pic32_reg_atomic *regs;
>> +	const void __iomem *base;
>> +	int v, nr_waits;
>> +	ulong rate;
>> +
>> +	/* cpu frequency in MHZ */
>> +	rate = clk_get_cpu_rate() / 1000000;
>> +
>> +	/* get flash ECC type */
>> +	base = pic32_get_syscfg_base();
>> +	v = (readl(base + CFGCON) >> ECC_SHIFT) & ECC_MASK;
>> +
>> +	if (v < 2) {
>> +		if (rate < 66)
>> +			nr_waits = 0;
>> +		else if (rate < 133)
>> +			nr_waits = 1;
>> +		else
>> +			nr_waits = 2;
>> +	} else {
>> +		if (rate <= 83)
>> +			nr_waits = 0;
>> +		else if (rate <= 166)
>> +			nr_waits = 1;
>> +		else
>> +			nr_waits = 2;
>> +	}
>> +
>> +	regs = ioremap(PREFETCH_BASE + PRECON, sizeof(*regs));
>> +	writel(nr_waits, &regs->raw);
>> +
>> +	/* Enable prefetch for all */
>> +	writel(0x30, &regs->set);
>> +	iounmap(regs);
>> +}
>> +
>> +/* arch specific CPU init after DM */
>> +int arch_cpu_init_dm(void)
>> +{
>> +	/* flash prefetch */
>> +	prefetch_init();
>> +	return 0;
>> +}
>> +
>> +/* Un-gate DDR2 modules (gated by default) */
>> +static void ddr2_pmd_ungate(void)
>> +{
>> +	void __iomem *regs;
>> +
>> +	regs = pic32_get_syscfg_base();
>> +	writel(0, regs + PMD7);
>> +}
>> +
>> +/* initialize the DDR2 Controller and DDR2 PHY */
>>  phys_size_t initdram(int board_type)
>>  {
>> +	ddr2_pmd_ungate();
>> +	ddr2_phy_init();
>> +	ddr2_ctrl_init();
>> +	return ddr2_calculate_size();
>> +}
>> +
>> +int misc_init_r(void)
>> +{
>> +	set_io_port_base(0);
>> +	return 0;
>> +}
>> +
>> +#ifdef CONFIG_DISPLAY_BOARDINFO
>> +const char *get_core_name(void)
>> +{
>> +	u32 proc_id;
>> +	const char *str;
>> +
>> +	proc_id = read_c0_prid();
>> +	switch (proc_id) {
>> +	case 0x19e28:
>> +		str = "PIC32MZ[DA]";
>> +		break;
>> +	default:
>> +		str = "UNKNOWN";
>> +	}
>> +
>> +	return str;
>> +}
>> +#endif
>> +#ifdef CONFIG_CMD_CLK
>> +int soc_clk_dump(void)
>> +{
>> +	int i, ret;
>> +	struct udevice *dev;
>> +
>> +	ret = uclass_get_device(UCLASS_CLK, 0, &dev);
>> +	if (ret) {
>> +		printf("clk-uclass not found\n");
>> +		return ret;
>> +	}
>> +
>> +	printf("PLL Speed: %lu MHz\n",
>> +	       CLK_MHZ(clk_get_periph_rate(dev, PLLCLK)));
>> +	printf("CPU Speed: %lu MHz\n", CLK_MHZ(clk_get_rate(dev)));
>> +	printf("MPLL Speed: %lu MHz\n",
>> +	       CLK_MHZ(clk_get_periph_rate(dev, MPLL)));
>> +
>> +	for (i = PB1CLK; i <= PB7CLK; i++)
>> +		printf("PB%d Clock Speed: %lu MHz\n", i - PB1CLK +
>> 1,
>> +		       CLK_MHZ(clk_get_periph_rate(dev, i)));
>> +
>> +	for (i = REF1CLK; i <= REF5CLK; i++)
>> +		printf("REFO%d Clock Speed: %lu MHz\n", i - REF1CLK
>> + 1,
>> +		       CLK_MHZ(clk_get_periph_rate(dev, i)));
>>  	return 0;
>>  }
>> +#endif
>> diff --git a/arch/mips/mach-pic32/include/mach/pic32.h
>> b/arch/mips/mach-pic32/include/mach/pic32.h
>> index 7e41810..16bfacf 100644
>> --- a/arch/mips/mach-pic32/include/mach/pic32.h
>> +++ b/arch/mips/mach-pic32/include/mach/pic32.h
>> @@ -73,4 +73,7 @@ static inline void __iomem
>> *pic32_get_syscfg_base(void)
>>  	return (void __iomem *)CKSEG1ADDR(PIC32_CFG_BASE);
>>  }
>>  
>> +/* Core */
>> +const char *get_core_name(void);
>> +
>>  #endif	/* __PIC32_REGS_H__ */
>> diff --git a/arch/mips/mach-pic32/lowlevel_init.S b/arch/mips/mach
>> -pic32/lowlevel_init.S
>> new file mode 100644
>> index 0000000..e37bebb
>> --- /dev/null
>> +++ b/arch/mips/mach-pic32/lowlevel_init.S
>> @@ -0,0 +1,27 @@
>> +/*
>> + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
>> + *
>> + * SPDX-License-Identifier:	GPL-2.0+
>> + *
>> +*/
>> +
>> +#include <config.h>
>> +#include <asm/regdef.h>
>> +#include <asm/mipsregs.h>
>> +#include <asm/asm.h>
>> +
>> +LEAF(lowlevel_init)
>> +	/*
>> +	 * Establish Cause
>> +	 * (set IV bit)
>> +	 */
>> +	li	t1, 0x00800000
>> +	mtc0	t1, CP0_CAUSE
>> +
>> +	/* Establish Wired (and Random) */
>> +	mtc0	zero, CP0_WIRED
>> +	 nop
>> +
>> +	jr	ra
>> +	 nop
>> +	END(lowlevel_init)
>> diff --git a/arch/mips/mach-pic32/reset.c b/arch/mips/mach
>> -pic32/reset.c
>> new file mode 100644
>> index 0000000..66c6833
>> --- /dev/null
>> +++ b/arch/mips/mach-pic32/reset.c
>> @@ -0,0 +1,36 @@
>> +/*
>> + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
>> + *
>> + * SPDX-License-Identifier:	GPL-2.0+
>> + *
>> + */
>> +
>> +#include <common.h>
>> +#include <asm/io.h>
>> +#include <mach/pic32.h>
>> +
>> +/* SYSKEY */
>> +#define UNLOCK_KEY1	0xaa996655
>> +#define UNLOCK_KEY2	0x556699aa
>> +#define LOCK_KEY	0
>> +
>> +#define RSWRST          0x1250
>> +
>> +void _machine_restart(void)
>> +{
>> +	void __iomem *base;
>> +
>> +	base = pic32_get_syscfg_base();
>> +
>> +	/* unlock sequence */
>> +	writel(LOCK_KEY, base + SYSKEY);
>> +	writel(UNLOCK_KEY1, base + SYSKEY);
>> +	writel(UNLOCK_KEY2, base + SYSKEY);
>> +
>> +	/* soft reset */
>> +	writel(0x1, base + RSWRST);
>> +	(void) readl(base + RSWRST);
>> +
>> +	while (1)
>> +		;
>> +}

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 03/14] drivers: clk: Add clock driver for Microchip PIC32 Microcontroller.
  2016-01-13 14:55   ` Tom Rini
@ 2016-01-14  6:04     ` Purna Chandra Mandal
  2016-01-14 12:30       ` Tom Rini
  0 siblings, 1 reply; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-14  6:04 UTC (permalink / raw)
  To: u-boot

On 01/13/2016 08:25 PM, Tom Rini wrote:

> On Tue, Jan 12, 2016 at 03:48:18PM +0530, Purna Chandra Mandal wrote:
>
>> PIC32 clock module consists of multiple oscillators, PLLs, mutiplexers
>> and dividers capable of supplying clock to various controllers
>> on or off-chip.
> [snip]
>>  include/dt-bindings/clock/microchip,clock.h        |  29 ++
> Has this been submitted for the kernel and reviewed there as well
> already?  Thanks!
>
Clock driver in kernel is under review.
[1] clock driver: https://lkml.org/lkml/2016/1/7/764
[0] clock binding: https://lkml.org/lkml/2016/1/7/762
 
Please note clock driver in Linux kernel is implemented in more elaborate/descriptive way - all the sub-modules are individually defined in device-tree (having "#clock-cells = <0>") and their phandles are directly
referred in clock clients so there was no need of having dt-binding header.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 06/14] drivers: serial: add driver for Microchip PIC32 UART controller.
  2016-01-13 20:09   ` Simon Glass
@ 2016-01-14  6:14     ` Purna Chandra Mandal
  0 siblings, 0 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-14  6:14 UTC (permalink / raw)
  To: u-boot

On 01/14/2016 01:39 AM, Simon Glass wrote:

> Hi Purna,
>
> On 12 January 2016 at 03:18, Purna Chandra Mandal
> <purna.mandal@microchip.com> wrote:
>> From: Paul Thacker <paul.thacker@microchip.com>
>>
>> This adds PIC32 UART controller support based on driver model.
>>
>> Signed-off-by: Paul Thacker <paul.thacker@microchip.com>
>> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
>>
>>
>> ---
>>
>> Changes in v3:
>> - remove ofdata_to_platdata, and replace platdata with priv
>> - remove special handling of '\r' as being handled by serial-uclass
>> - remove loop to wait for space in tx buffer before pumping char
>>
>> Changes in v2:
>> - fix missing/corrupted chars during baud rate change
>> - remove loop until any char is avaialbale in getc()
>>
>>  .../serial/microchip,pic32-uart.txt                |   5 +
>>  drivers/serial/Kconfig                             |  13 ++
>>  drivers/serial/Makefile                            |   1 +
>>  drivers/serial/serial_pic32.c                      | 199 +++++++++++++++++++++
>>  4 files changed, 218 insertions(+)
>>  create mode 100644 doc/device-tree-bindings/serial/microchip,pic32-uart.txt
>>  create mode 100644 drivers/serial/serial_pic32.c
>>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> One nit/question below.
>
>> diff --git a/doc/device-tree-bindings/serial/microchip,pic32-uart.txt b/doc/device-tree-bindings/serial/microchip,pic32-uart.txt
>> new file mode 100644
>> index 0000000..f00e215
>> --- /dev/null
>> +++ b/doc/device-tree-bindings/serial/microchip,pic32-uart.txt
>> @@ -0,0 +1,5 @@
>> +* Microchip PIC32 serial UART
>> +
>> +Required properties:
>> +- compatible: must be "microchip,pic32mzda-uart".
>> +- reg: exactly one register range.
>> diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
>> index 1fc287e..9763ea1 100644
>> --- a/drivers/serial/Kconfig
>> +++ b/drivers/serial/Kconfig
>> @@ -107,6 +107,14 @@ config DEBUG_UART_APBUART
>>           will need to provide parameters to make this work. The driver will
>>           be available until the real driver model serial is running.
>>
>> +config DEBUG_UART_PIC32
>> +       bool "Microchip PIC32"
>> +       help
>> +         Select this to enable a debug UART using the serial_pic32 driver. You
>> +         will need to provide parameters to make this work. The driver will
>> +         be available until the real driver model serial is running.
>> +
>> +
>>  endchoice
>>
>>  config DEBUG_UART_BASE
>> @@ -223,4 +231,9 @@ config UNIPHIER_SERIAL
>>           If you have a UniPhier based board and want to use the on-chip
>>           serial ports, say Y to this option. If unsure, say N.
>>
>> +config PIC32_SERIAL
>> +       bool "Support for Microchip PIC32 on-chip UART"
>> +       help
>> +         Support for the UART found on Microchip PIC32 SoC's.
>> +
>>  endmenu
>> diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
>> index dd87147..57cd38b 100644
>> --- a/drivers/serial/Makefile
>> +++ b/drivers/serial/Makefile
>> @@ -41,6 +41,7 @@ obj-$(CONFIG_MXS_AUART) += mxs_auart.o
>>  obj-$(CONFIG_ARC_SERIAL) += serial_arc.o
>>  obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o
>>  obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o
>> +obj-$(CONFIG_PIC32_SERIAL) += serial_pic32.o
>>
>>  ifndef CONFIG_SPL_BUILD
>>  obj-$(CONFIG_USB_TTY) += usbtty.o
>> diff --git a/drivers/serial/serial_pic32.c b/drivers/serial/serial_pic32.c
>> new file mode 100644
>> index 0000000..ee9d056
>> --- /dev/null
>> +++ b/drivers/serial/serial_pic32.c
>> @@ -0,0 +1,199 @@
>> +/*
>> + * (c) 2015 Paul Thacker <paul.thacker@microchip.com>
>> + *
>> + * SPDX-License-Identifier:    GPL-2.0+
>> + *
>> + */
>> +#include <common.h>
>> +#include <clk.h>
>> +#include <dm.h>
>> +#include <serial.h>
>> +#include <wait_bit.h>
>> +#include <mach/pic32.h>
>> +#include <dt-bindings/clock/microchip,clock.h>
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +/* UART Control Registers */
>> +#define U_MOD          0x00
>> +#define U_MODCLR       (U_MOD + _CLR_OFFSET)
>> +#define U_MODSET       (U_MOD + _SET_OFFSET)
>> +#define U_STA          0x10
>> +#define U_STACLR       (U_STA + _CLR_OFFSET)
>> +#define U_STASET       (U_STA + _SET_OFFSET)
>> +#define U_TXR          0x20
>> +#define U_RXR          0x30
>> +#define U_BRG          0x40
>> +
>> +/* U_MOD bits */
>> +#define UART_ENABLE            BIT(15)
>> +
>> +/* U_STA bits */
>> +#define UART_RX_ENABLE         BIT(12)
>> +#define UART_TX_BRK            BIT(11)
>> +#define UART_TX_ENABLE         BIT(10)
>> +#define UART_TX_FULL           BIT(9)
>> +#define UART_TX_EMPTY          BIT(8)
>> +#define UART_RX_OERR           BIT(1)
>> +#define UART_RX_DATA_AVAIL     BIT(0)
>> +
>> +struct pic32_uart_priv {
>> +       void __iomem *base;
>> +       ulong uartclk;
>> +};
>> +
>> +/*
>> + * Initialize the serial port with the given baudrate.
>> + * The settings are always 8 data bits, no parity, 1 stop bit, no start bits.
>> + */
>> +static int pic32_serial_init(void __iomem *base, ulong clk, u32 baudrate)
>> +{
>> +       u32 div = DIV_ROUND_CLOSEST(clk, baudrate * 16);
>> +
>> +       /* wait for TX FIFO to empty */
>> +       wait_for_bit(__func__, base + U_STA, UART_TX_EMPTY,
>> +                    true, CONFIG_SYS_HZ, false);
>> +
>> +       /* send break */
>> +       writel(UART_TX_BRK, base + U_STASET);
>> +
>> +       /* disable and clear mode */
>> +       writel(0, base + U_MOD);
>> +       writel(0, base + U_STA);
>> +
>> +       /* set baud rate generator */
>> +       writel(div - 1, base + U_BRG);
>> +
>> +       /* enable the UART for TX and RX */
>> +       writel(UART_TX_ENABLE | UART_RX_ENABLE, base + U_STASET);
>> +
>> +       /* enable the UART */
>> +       writel(UART_ENABLE, base + U_MODSET);
>> +       return 0;
>> +}
>> +
>> +/* Check number of characters ready in RX Fifo */
> But what does it return? The number of available characters? Please
> make the comment more specific.

Good catch.
In PIC32 there is no way to know number of outstanding/pending chars in rx-fifo. Only it can be known whether there is any. I'll update the comment accordingly. 
Specifically bitwise ANDing with 'UART_RX_DATA_AVAIL' (=BIT(0)) makes result always binary (0, or 1).

>> +static int pic32_uart_pending_input(void __iomem *base)
>> +{
>> +       /* check if rx buffer overrun error has occurred */
>> +       if (readl(base + U_STA) & UART_RX_OERR) {
>> +               readl(base + U_RXR);
>> +
>> +               /* clear OERR to keep receiving */
>> +               writel(UART_RX_OERR, base + U_STACLR);
>> +       }
>> +
>> +       return readl(base + U_STA) & UART_RX_DATA_AVAIL;
>> +}
>> +
>> +static int pic32_uart_pending(struct udevice *dev, bool input)
>> +{
>> +       struct pic32_uart_priv *priv = dev_get_priv(dev);
>> +
>> +       if (input)
>> +               return pic32_uart_pending_input(priv->base);
> Should return the number of characters available. Should this be?
>
>                return pic32_uart_pending_input(priv->base) ? 1 : 0;
>
> Of course I don't quite know what pic32_uart_pending_input() does, so
> I could be wrong.

It returns in binary (0 or 1) due to short-coming in controller.

>> +
>> +       return !(readl(priv->base + U_STA) & UART_TX_EMPTY);
>> +}
>> +
>> +static int pic32_uart_setbrg(struct udevice *dev, int baudrate)
>> +{
>> +       struct pic32_uart_priv *priv = dev_get_priv(dev);
>> +
>> +       return pic32_serial_init(priv->base, priv->uartclk, baudrate);
>> +}
>> +
>> +static int pic32_uart_putc(struct udevice *dev, const char ch)
>> +{
>> +       struct pic32_uart_priv *priv = dev_get_priv(dev);
>> +
>> +       /* Check if Tx FIFO is full */
>> +       if (readl(priv->base + U_STA) & UART_TX_FULL)
>> +               return -EAGAIN;
>> +
>> +       /* pump the char to tx buffer */
>> +       writel(ch, priv->base + U_TXR);
>> +
>> +       return 0;
>> +}
>> +
>> +static int pic32_uart_getc(struct udevice *dev)
>> +{
>> +       struct pic32_uart_priv *priv = dev_get_priv(dev);
>> +
>> +       /* return error if RX fifo is empty */
>> +       if (!pic32_uart_pending_input(priv->base))
>> +               return -EAGAIN;
>> +
>> +       /* read the character from rx buffer */
>> +       return readl(priv->base + U_RXR) & 0xff;
>> +}
>> +
>> +static int pic32_uart_probe(struct udevice *dev)
>> +{
>> +       struct pic32_uart_priv *priv = dev_get_priv(dev);
>> +       struct udevice *clkdev;
>> +       fdt_addr_t addr;
>> +       fdt_size_t size;
>> +       int ret;
>> +
>> +       /* get address */
>> +       addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg", &size);
>> +       if (addr == FDT_ADDR_T_NONE)
>> +               return -EINVAL;
>> +
>> +       priv->base = ioremap(addr, size);
>> +       if (!priv->base)
>> +               return -EINVAL;
>> +
>> +       /* get clock rate */
>> +       ret = uclass_get_device(UCLASS_CLK, 0, &clkdev);
>> +       if (ret) {
>> +               printf("clk class not found, %d\n", ret);
>> +               return ret;
>> +       }
>> +       priv->uartclk = clk_get_periph_rate(clkdev, PB2CLK);
>> +
>> +       /* initialize serial */
>> +       return pic32_serial_init(priv->base, priv->uartclk, CONFIG_BAUDRATE);
>> +}
>> +
>> +static const struct dm_serial_ops pic32_uart_ops = {
>> +       .putc           = pic32_uart_putc,
>> +       .pending        = pic32_uart_pending,
>> +       .getc           = pic32_uart_getc,
>> +       .setbrg         = pic32_uart_setbrg,
>> +};
>> +
>> +static const struct udevice_id pic32_uart_ids[] = {
>> +       { .compatible = "microchip,pic32mzda-uart" },
>> +       {}
>> +};
>> +
>> +U_BOOT_DRIVER(pic32_serial) = {
>> +       .name           = "pic32-uart",
>> +       .id             = UCLASS_SERIAL,
>> +       .of_match       = pic32_uart_ids,
>> +       .probe          = pic32_uart_probe,
>> +       .ops            = &pic32_uart_ops,
>> +       .flags          = DM_FLAG_PRE_RELOC,
>> +       .priv_auto_alloc_size = sizeof(struct pic32_uart_priv),
>> +};
>> +
>> +#ifdef CONFIG_DEBUG_UART_PIC32
>> +#include <debug_uart.h>
>> +
>> +static inline void _debug_uart_init(void)
>> +{
>> +       void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE;
>> +
>> +       pic32_serial_init(base, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
>> +}
>> +
>> +static inline void _debug_uart_putc(int ch)
>> +{
>> +       writel(ch, CONFIG_DEBUG_UART_BASE + U_TXR);
>> +}
>> +
>> +DEBUG_UART_FUNCS
>> +#endif
>> --
>> 1.8.3.1
>>
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 09/14] board: Add Microchip PIC32MZ[DA]-Starter-Kit board.
  2016-01-13 14:56   ` Tom Rini
@ 2016-01-14  6:40     ` Purna Chandra Mandal
  0 siblings, 0 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-14  6:40 UTC (permalink / raw)
  To: u-boot

On 01/13/2016 08:26 PM, Tom Rini wrote:
> On Tue, Jan 12, 2016 at 03:48:24PM +0530, Purna Chandra Mandal wrote:
>
>> This adds support for Microchip PIC32MZ[DA] StarterKit board
>> based on a PIC32MZ[DA] family of microcontroller.
>>
>> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> [snip]
>> diff --git a/configs/pic32mzdask_defconfig b/configs/pic32mzdask_defconfig
>> new file mode 100644
>> index 0000000..3483eb0
>> --- /dev/null
>> +++ b/configs/pic32mzdask_defconfig
>> @@ -0,0 +1,416 @@
>> +#
>> +# Automatically generated file; DO NOT EDIT.
>> +# U-Boot 2016.01-rc3 Configuration
> Please use 'make savedefconfig' to generate this file instead, it will
> be much smaller (and this is also what you do with the linux kernel).

ack. Will do.

>> +++ b/include/configs/pic32mzdask.h
> [snip]
>> +#define CONFIG_SYS_BAUDRATE_TABLE	{9600, 19200, 38400, 57600, 115200}
> I think you can use the default here.

ack. Will drop this to use fallback one.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 11/14] board: add SDHCI support for PIC32MZDASK board.
  2016-01-13 14:56   ` Tom Rini
@ 2016-01-14  8:31     ` Purna Chandra Mandal
  0 siblings, 0 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-14  8:31 UTC (permalink / raw)
  To: u-boot

On 01/13/2016 08:26 PM, Tom Rini wrote:
> On Tue, Jan 12, 2016 at 03:48:26PM +0530, Purna Chandra Mandal wrote:
>
>> Enable MMC, SDHCI, FAT FS, EXT4 FS support for PIC32MZ[DA] StarterKit.
>> Also add custom scripts, rules to boot Linux from microSD card.
>>
>> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> [snip]
>> +#define CONFIG_EXTRA_ENV_SETTINGS				\
>> +	"loadaddr="__stringify(CONFIG_SYS_LOAD_ADDR)"\0"	\
>> +	"uenvfile=uEnv.txt\0"					\
>> +	"uenvaddr="__stringify(CONFIG_SYS_ENV_ADDR)"\0"		\
>> +	"scriptfile=boot.scr\0"					\
>> +	"ubootfile=u-boot.bin\0"				\
>> +	"importbootenv= "					\
>> +		"env import -t -r ${uenvaddr} ${filesize};\0"	\
>> +								\
>> +	"mmcloadenv=fatload mmc 0 ${uenvaddr} ${uenvfile}\0"	\
>> +	"mmcloadscr=fatload mmc 0 ${uenvaddr} ${scriptfile}\0"	\
>> +	"mmcloadub=fatload mmc 0 ${loadaddr} ${ubootfile}\0"	\
>> +								\
>> +	"loadbootenv=run mmcloadenv\0"				\
>> +	"loadbootscr=run mmcloadscr\0"				\
>> +	"bootcmd_root= "					\
>> +		"if run loadbootenv; then "			\
>> +			"echo Loaded environment ${uenvfile}; "	\
>> +			"run importbootenv; "			\
>> +		"fi; "						\
>> +		"if test -n \"${bootcmd_uenv}\" ; then "	\
>> +			"echo Running bootcmd_uenv ...; "	\
>> +			"run bootcmd_uenv; "			\
>> +		"fi; "						\
>> +		"if run loadbootscr; then "			\
>> +			"echo Jumping to ${scriptfile}; "	\
>> +			"source ${uenvaddr}; "			\
>> +		"fi; "						\
>> +		"echo Custom environment or script not found. "	\
>> +			"Aborting auto booting...; \0"		\
>> +	""
>> +
>> +#define CONFIG_BOOTCOMMAND		"run bootcmd_root"
> I would like to see the env above done as a separate commit and then
> using config_distro_default / bootcmd :)

agreed. Will add in separate commit and using config_distro_default(/bootcmd).h.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 09/14] board: Add Microchip PIC32MZ[DA]-Starter-Kit board.
  2016-01-13 15:03   ` Daniel Schwierzeck
@ 2016-01-14  8:40     ` Purna Chandra Mandal
  0 siblings, 0 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-14  8:40 UTC (permalink / raw)
  To: u-boot

On 01/13/2016 08:33 PM, Daniel Schwierzeck wrote:

> Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra Mandal:
>> This adds support for Microchip PIC32MZ[DA] StarterKit board
>> based on a PIC32MZ[DA] family of microcontroller.
>>
>> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
>>
>>
>> ---
>>
>> Changes in v3:
>> - drop SKIP_LOWLEVEL_INIT, GBL_DATA_OFFSET from config header
>> - move CMD_MEMTEST, CMD_MEMINFO to defconfig
>> - increase SYS_MALLOC_F_LEN to 0x600
>> - use auto-generated defconfig - no hand edit
>>
>> Changes in v2:
>> - move CONFIG_SYS_TEXT_BASE (from board/*/config.mk) to
>> include/configs/<board>.h
>>
>>  arch/mips/dts/Makefile                |   2 +-
>>  arch/mips/dts/pic32mzda_sk.dts        |  38 ++++
>>  arch/mips/mach-pic32/Kconfig          |  13 ++
>>  board/microchip/pic32mzda/Kconfig     |  13 ++
>>  board/microchip/pic32mzda/MAINTAINERS |   6 +
>>  board/microchip/pic32mzda/Makefile    |   7 +
>>  board/microchip/pic32mzda/README      |  22 ++
>>  board/microchip/pic32mzda/pic32mzda.c |  31 +++
>>  configs/pic32mzdask_defconfig         | 416
>> ++++++++++++++++++++++++++++++++++
>>  include/configs/pic32mzdask.h         |  94 ++++++++
>>  10 files changed, 641 insertions(+), 1 deletion(-)
>>  create mode 100644 arch/mips/dts/pic32mzda_sk.dts
>>  create mode 100644 board/microchip/pic32mzda/Kconfig
>>  create mode 100644 board/microchip/pic32mzda/MAINTAINERS
>>  create mode 100644 board/microchip/pic32mzda/Makefile
>>  create mode 100644 board/microchip/pic32mzda/README
>>  create mode 100644 board/microchip/pic32mzda/pic32mzda.c
>>  create mode 100644 configs/pic32mzdask_defconfig
>>  create mode 100644 include/configs/pic32mzdask.h
>>
>> diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile
>> index 47b6eb5..b513918 100644
>> --- a/arch/mips/dts/Makefile
>> +++ b/arch/mips/dts/Makefile
>> @@ -2,7 +2,7 @@
>>  # SPDX-License-Identifier:	GPL-2.0+
>>  #
>>  
>> -dtb-y +=
>> +dtb-$(CONFIG_TARGET_PIC32MZDASK) += pic32mzda_sk.dtb
>>  
>>  targets += $(dtb-y)
>>  
>> diff --git a/arch/mips/dts/pic32mzda_sk.dts
>> b/arch/mips/dts/pic32mzda_sk.dts
>> new file mode 100644
>> index 0000000..99e7f64
>> --- /dev/null
>> +++ b/arch/mips/dts/pic32mzda_sk.dts
>> @@ -0,0 +1,38 @@
>> +/*
>> + * Copyright (C) 2015 Purna Chandra Mandal, 
>> purna.mandal at microchip.com
>> + *
>> + * SPDX-License-Identifier:	GPL-2.0+
>> + */
>> +
>> +/dts-v1/;
>> +
>> +#include "pic32mzda.dtsi"
>> +
>> +/ {
>> +	model = "Microchip PIC32MZDASK";
>> +	compatible = "microchip,pic32mzdask", "microchip,pic32mzda";
>> +
>> +	aliases {
>> +		console = &uart2;
>> +		serial0 = &uart2;
>> +	};
>> +
>> +	chosen {
>> +		stdout-path = "serial0:115200n8";
>> +	};
>> +};
>> +
>> +&clock {
>> +	status = "okay";
>> +	u-boot,dm-pre-reloc;
>> +};
>> +
>> +&pinctrl {
>> +	status = "okay";
>> +	u-boot,dm-pre-reloc;
>> +};
>> +
>> +&uart2 {
>> +	status = "okay";
>> +	u-boot,dm-pre-reloc;
>> +};
>> diff --git a/arch/mips/mach-pic32/Kconfig b/arch/mips/mach
>> -pic32/Kconfig
>> index 74be9fb..d665f63 100644
>> --- a/arch/mips/mach-pic32/Kconfig
>> +++ b/arch/mips/mach-pic32/Kconfig
>> @@ -22,4 +22,17 @@ config SOC_PIC32MZDA
>>  
>>  endchoice
>>  
>> +choice
>> +	prompt "Board select"
>> +
>> +config TARGET_PIC32MZDASK
>> +	bool "Microchip PIC32MZ[DA] Starter Kit"
>> +	depends on SOC_PIC32MZDA
>> +	help
>> +	  This supports Microchip PIC32MZ[DA] Starter Kit.
>> +
>> +endchoice
>> +
>> +source "board/microchip/pic32mzda/Kconfig"
>> +
>>  endmenu
>> diff --git a/board/microchip/pic32mzda/Kconfig
>> b/board/microchip/pic32mzda/Kconfig
>> new file mode 100644
>> index 0000000..8acb393
>> --- /dev/null
>> +++ b/board/microchip/pic32mzda/Kconfig
>> @@ -0,0 +1,13 @@
>> +
>> +if TARGET_PIC32MZDASK
>> +
>> +config SYS_BOARD
>> +	default "pic32mzda"
>> +
>> +config SYS_VENDOR
>> +	default "microchip"
>> +
>> +config SYS_CONFIG_NAME
>> +	default "pic32mzdask"
>> +
>> +endif
>> diff --git a/board/microchip/pic32mzda/MAINTAINERS
>> b/board/microchip/pic32mzda/MAINTAINERS
>> new file mode 100644
>> index 0000000..c934f1a
>> --- /dev/null
>> +++ b/board/microchip/pic32mzda/MAINTAINERS
>> @@ -0,0 +1,6 @@
>> +PIC32MZDASK BOARD
>> +M:	Purna Chandra Mandal <purna.mandal@microchip.com>
>> +S:	Maintained
>> +F:	board/microchip/pic32mzda/
>> +F:	include/configs/pic32mzdask.h
>> +F:	configs/pic32mzdask_defconfig
>> diff --git a/board/microchip/pic32mzda/Makefile
>> b/board/microchip/pic32mzda/Makefile
>> new file mode 100644
>> index 0000000..3629530
>> --- /dev/null
>> +++ b/board/microchip/pic32mzda/Makefile
>> @@ -0,0 +1,7 @@
>> +#
>> +# (C) Copyright 2015
>> +# Purna Chandra Mandal, purna.mandal at microchip.com.
>> +#
>> +# SPDX-License-Identifier:      GPL-2.0+
>> +#
>> +obj-y := pic32mzda.o
>> diff --git a/board/microchip/pic32mzda/README
>> b/board/microchip/pic32mzda/README
>> new file mode 100644
>> index 0000000..91d16ab
>> --- /dev/null
>> +++ b/board/microchip/pic32mzda/README
>> @@ -0,0 +1,22 @@
>> +/*
>> + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
>> + */
>> +
>> +PIC32MZ[DA] Starter Kit
>> +----------------------------------------
>> +PIC32MZ[DA] Starter Kit is based on PIC32MZ[DA] family of micro
>> -controller.
>> +This family is powered by MIPS M14KEC 32bit general purpose core and
>> has
>> +advanced microcontroller features and peripherals.
>> +
>> +This processor boots with proprietary stage1 bootloader running from
>> internal
>> +boot-flash. Stage1 bootloader inturns locates and jumps to U-Boot
>> programmed
>> +on internal program-flash. Finally U-Boot loads OS image (along with
>> other
>> +required files for booting) from either uSD card, or ethernet, or
>> from USB
>> +storage.
>> +
>> +To boot Linux following three files are mandatory - uEnv.txt (custom
>> U-Boot
>> +environment file), uImage, *.dtb (platform device-tree-blob file).
>> +
>> +U-Boot jumps to Linux using UHI specification.
>> +
>> +Visit http://microchip.com for details.
>> diff --git a/board/microchip/pic32mzda/pic32mzda.c
>> b/board/microchip/pic32mzda/pic32mzda.c
>> new file mode 100644
>> index 0000000..afe2ab8
>> --- /dev/null
>> +++ b/board/microchip/pic32mzda/pic32mzda.c
>> @@ -0,0 +1,31 @@
>> +/*
>> + * Microchip PIC32MZ[DA] Starter Kit board
>> + *
>> + * Copyright (C) 2015, Microchip Technology Inc.
>> + * Purna Chandra Mandal <purna.mandal@microchip.com>
>> + *
>> + * SPDX-License-Identifier:	GPL-2.0+
>> + *
>> + */
>> +
>> +#include <common.h>
>> +#include <dm.h>
>> +#include <clk.h>
>> +#include <mach/pic32.h>
>> +
>> +#ifdef CONFIG_DISPLAY_BOARDINFO
>> +int checkboard(void)
>> +{
>> +	ulong rate = 0;
>> +	struct udevice *dev;
>> +
>> +	printf("Core: %s\n", get_core_name());
>> +
>> +	if (!uclass_get_device(UCLASS_CLK, 0, &dev)) {
>> +		rate = clk_get_rate(dev);
>> +		printf("CPU Speed: %lu MHz\n", rate / 1000000);
>> +	}
>> +
>> +	return 0;
>> +}
>> +#endif
>> diff --git a/configs/pic32mzdask_defconfig
>> b/configs/pic32mzdask_defconfig
>> new file mode 100644
>> index 0000000..3483eb0
>> --- /dev/null
>> +++ b/configs/pic32mzdask_defconfig
>> @@ -0,0 +1,416 @@
>> +#
>> +# Automatically generated file; DO NOT EDIT.
>> +# U-Boot 2016.01-rc3 Configuration
>> +#
> this is not a defconfig file. Please create it like that (after you
> fixed the remaining Kconfig issues in your other patches)
>
> $ make pic32mzdask_defconfig
>
> $ make menuconfig (optionally, if you want to change some options)
>
> $ make savedefconfig
> $ cp defconfig configs/pic32mzdask_defconfig
>
> The purpose is, that all options with "default y" or "select XYZ" are
> filtered out and that you only store the options different from the
> default ones.

ack. Will update accordingly.

> With your current configuration, your defconfig file would look like
> this:
>
> CONFIG_MIPS=y
> CONFIG_SYS_MALLOC_F_LEN=0x600
> CONFIG_DM_GPIO=y
> CONFIG_MACH_PIC32=y
> # CONFIG_MIPS_BOOT_ENV_LEGACY is not set
> CONFIG_MIPS_BOOT_FDT=y
> CONFIG_DEFAULT_DEVICE_TREE="pic32mzda_sk"
> CONFIG_HUSH_PARSER=y
> CONFIG_SYS_PROMPT="dask # "
> # CONFIG_CMD_IMLS is not set
> # CONFIG_CMD_SAVEENV is not set
> CONFIG_LOOPW=y
> CONFIG_CMD_MEMTEST=y
> CONFIG_CMD_MEMINFO=y
> # CONFIG_CMD_FLASH is not set
> # CONFIG_CMD_FPGA is not set
> CONFIG_CMD_GPIO=y
> CONFIG_CMD_RARP=y
> CONFIG_CMD_DHCP=y
> CONFIG_CMD_PING=y
> CONFIG_CMD_TIME=y
> CONFIG_OF_EMBED=y
> CONFIG_NET_RANDOM_ETHADDR=y
> CONFIG_CLK=y
> CONFIG_DM_MMC=y
> CONFIG_PIC32_SDHCI=y
> CONFIG_DM_ETH=y
> CONFIG_PHYLIB=y
> CONFIG_PIC32_ETH=y
> CONFIG_PINCTRL=y
> # CONFIG_PINCTRL_FULL is not set
> CONFIG_SYS_VSNPRINTF=y
> CONFIG_USE_TINY_PRINTF=y
> CONFIG_CMD_DHRYSTONE=y
>
>
>
>> +CONFIG_HAVE_GENERIC_BOARD=y
>> +CONFIG_SYS_GENERIC_BOARD=y
>> +# CONFIG_ARC is not set
>> +# CONFIG_ARM is not set
>> +# CONFIG_AVR32 is not set
>> +# CONFIG_BLACKFIN is not set
>> +# CONFIG_M68K is not set
>> +# CONFIG_MICROBLAZE is not set
>> +CONFIG_MIPS=y
>> +# CONFIG_NDS32 is not set
>> +# CONFIG_NIOS2 is not set
>> +# CONFIG_OPENRISC is not set
>> +# CONFIG_PPC is not set
>> +# CONFIG_SANDBOX is not set
>> +# CONFIG_SH is not set
>> +# CONFIG_SPARC is not set
>> +# CONFIG_X86 is not set
>> +CONFIG_SYS_ARCH="mips"
>> +CONFIG_SYS_CPU="mips32"
>> +CONFIG_SYS_SOC="pic32mzda"
>> +CONFIG_SYS_VENDOR="microchip"
>> +CONFIG_SYS_BOARD="pic32mzda"
>> +CONFIG_SYS_CONFIG_NAME="pic32mzdask"
>> +CONFIG_SYS_MALLOC_F_LEN=0x600
>> +CONFIG_SYS_MALLOC_F=y
>> +CONFIG_DM_SERIAL=y
>> +# CONFIG_DM_SPI is not set
>> +# CONFIG_DM_I2C is not set
>> +CONFIG_DM_GPIO=y
>> +
>> +#
>> +# MIPS architecture
>> +#
>> +# CONFIG_TARGET_QEMU_MIPS is not set
>> +# CONFIG_TARGET_MALTA is not set
>> +# CONFIG_TARGET_VCT is not set
>> +# CONFIG_TARGET_DBAU1X00 is not set
>> +# CONFIG_TARGET_PB1X00 is not set
>> +CONFIG_MACH_PIC32=y
>> +
>> +#
>> +# Microchip PIC32 platforms
>> +#
>> +CONFIG_SOC_PIC32MZDA=y
>> +CONFIG_TARGET_PIC32MZDASK=y
>> +CONFIG_SYS_LITTLE_ENDIAN=y
>> +# CONFIG_CPU_MIPS32_R1 is not set
>> +CONFIG_CPU_MIPS32_R2=y
>> +
>> +#
>> +# OS boot interface
>> +#
>> +CONFIG_MIPS_BOOT_CMDLINE_LEGACY=y
>> +# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
>> +CONFIG_MIPS_BOOT_FDT=y
>> +CONFIG_SUPPORTS_LITTLE_ENDIAN=y
>> +CONFIG_SUPPORTS_CPU_MIPS32_R1=y
>> +CONFIG_SUPPORTS_CPU_MIPS32_R2=y
>> +CONFIG_CPU_MIPS32=y
>> +CONFIG_32BIT=y
>> +CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD=y
>> +CONFIG_MIPS_L1_CACHE_SHIFT_4=y
>> +CONFIG_MIPS_L1_CACHE_SHIFT=4
>> +# CONFIG_DM_KEYBOARD is not set
>> +CONFIG_DEFAULT_DEVICE_TREE="pic32mzda_sk"
>> +
>> +#
>> +# General setup
>> +#
>> +CONFIG_LOCALVERSION=""
>> +CONFIG_LOCALVERSION_AUTO=y
>> +CONFIG_CC_OPTIMIZE_FOR_SIZE=y
>> +CONFIG_EXPERT=y
>> +CONFIG_SYS_MALLOC_CLEAR_ON_INIT=y
>> +
>> +#
>> +# Boot images
>> +#
>> +# CONFIG_FIT is not set
>> +CONFIG_SYS_EXTRA_OPTIONS=""
>> +
>> +#
>> +# Command line interface
>> +#
>> +CONFIG_HUSH_PARSER=y
>> +CONFIG_SYS_HUSH_PARSER=y
>> +CONFIG_SYS_PROMPT="dask # "
>> +
>> +#
>> +# Autoboot options
>> +#
>> +# CONFIG_AUTOBOOT_KEYED is not set
>> +
>> +#
>> +# Commands
>> +#
>> +
>> +#
>> +# Info commands
>> +#
>> +CONFIG_CMD_BDI=y
>> +CONFIG_CMD_CONSOLE=y
>> +# CONFIG_CMD_CPU is not set
>> +# CONFIG_CMD_LICENSE is not set
>> +
>> +#
>> +# Boot commands
>> +#
>> +CONFIG_CMD_BOOTD=y
>> +CONFIG_CMD_BOOTM=y
>> +CONFIG_CMD_ELF=y
>> +CONFIG_CMD_GO=y
>> +CONFIG_CMD_RUN=y
>> +CONFIG_CMD_IMI=y
>> +# CONFIG_CMD_IMLS is not set
>> +CONFIG_CMD_XIMG=y
>> +
>> +#
>> +# Environment commands
>> +#
>> +# CONFIG_CMD_EXPORTENV is not set
>> +CONFIG_CMD_IMPORTENV=y
>> +CONFIG_CMD_EDITENV=y
>> +# CONFIG_CMD_SAVEENV is not set
>> +CONFIG_CMD_ENV_EXISTS=y
>> +
>> +#
>> +# Memory commands
>> +#
>> +CONFIG_CMD_MEMORY=y
>> +CONFIG_CMD_CRC32=y
>> +CONFIG_LOOPW=y
>> +CONFIG_CMD_MEMTEST=y
>> +# CONFIG_CMD_MX_CYCLIC is not set
>> +CONFIG_CMD_MEMINFO=y
>> +
>> +#
>> +# Device access commands
>> +#
>> +CONFIG_CMD_DM=y
>> +# CONFIG_CMD_DEMO is not set
>> +CONFIG_CMD_LOADB=y
>> +CONFIG_CMD_LOADS=y
>> +# CONFIG_CMD_FLASH is not set
>> +# CONFIG_CMD_NAND is not set
>> +# CONFIG_CMD_SF is not set
>> +# CONFIG_CMD_SPI is not set
>> +# CONFIG_CMD_I2C is not set
>> +# CONFIG_CMD_USB is not set
>> +# CONFIG_CMD_FPGA is not set
>> +CONFIG_CMD_GPIO=y
>> +
>> +#
>> +# Shell scripting commands
>> +#
>> +CONFIG_CMD_ECHO=y
>> +CONFIG_CMD_ITEST=y
>> +CONFIG_CMD_SOURCE=y
>> +CONFIG_CMD_SETEXPR=y
>> +
>> +#
>> +# Network commands
>> +#
>> +# CONFIG_CMD_NET is not set
>> +# CONFIG_CMD_TFTPPUT is not set
>> +# CONFIG_CMD_TFTPSRV is not set
>> +# CONFIG_CMD_RARP is not set
>> +# CONFIG_CMD_DHCP is not set
>> +# CONFIG_CMD_NFS is not set
>> +# CONFIG_CMD_PING is not set
>> +# CONFIG_CMD_CDP is not set
>> +# CONFIG_CMD_SNTP is not set
>> +# CONFIG_CMD_DNS is not set
>> +# CONFIG_CMD_LINK_LOCAL is not set
>> +
>> +#
>> +# Misc commands
>> +#
>> +CONFIG_CMD_TIME=y
>> +CONFIG_CMD_MISC=y
>> +# CONFIG_CMD_TIMER is not set
>> +
>> +#
>> +# Boot timing
>> +#
>> +# CONFIG_BOOTSTAGE is not set
>> +CONFIG_BOOTSTAGE_USER_COUNT=20
>> +CONFIG_BOOTSTAGE_STASH_ADDR=0
>> +CONFIG_BOOTSTAGE_STASH_SIZE=4096
>> +
>> +#
>> +# Power commands
>> +#
>> +
>> +#
>> +# Security commands
>> +#
>> +# CONFIG_CONSOLE_RECORD is not set
>> +CONFIG_SUPPORT_OF_CONTROL=y
>> +
>> +#
>> +# Device Tree Control
>> +#
>> +CONFIG_OF_CONTROL=y
>> +# CONFIG_OF_SEPARATE is not set
>> +CONFIG_OF_EMBED=y
>> +# CONFIG_NET is not set
>> +
>> +#
>> +# Device Drivers
>> +#
>> +
>> +#
>> +# Generic Driver Options
>> +#
>> +CONFIG_DM=y
>> +CONFIG_DM_WARN=y
>> +CONFIG_DM_DEVICE_REMOVE=y
>> +CONFIG_DM_STDIO=y
>> +CONFIG_DM_SEQ_ALIAS=y
>> +# CONFIG_REGMAP is not set
>> +# CONFIG_SPL_REGMAP is not set
>> +# CONFIG_DEVRES is not set
>> +CONFIG_SIMPLE_BUS=y
>> +CONFIG_OF_TRANSLATE=y
>> +# CONFIG_ADC is not set
>> +# CONFIG_ADC_EXYNOS is not set
>> +# CONFIG_ADC_SANDBOX is not set
>> +CONFIG_CLK=y
>> +# CONFIG_SPL_CLK is not set
>> +# CONFIG_CPU is not set
>> +
>> +#
>> +# Hardware crypto devices
>> +#
>> +# CONFIG_FSL_CAAM is not set
>> +
>> +#
>> +# Demo for driver model
>> +#
>> +# CONFIG_DM_DEMO is not set
>> +
>> +#
>> +# DFU support
>> +#
>> +# CONFIG_DFU_TFTP is not set
>> +
>> +#
>> +# GPIO Support
>> +#
>> +# CONFIG_ALTERA_PIO is not set
>> +# CONFIG_DWAPB_GPIO is not set
>> +# CONFIG_ATMEL_PIO4 is not set
>> +# CONFIG_LPC32XX_GPIO is not set
>> +# CONFIG_ROCKCHIP_GPIO is not set
>> +# CONFIG_VYBRID_GPIO is not set
>> +CONFIG_PIC32_GPIO=y
>> +
>> +#
>> +# I2C support
>> +#
>> +# CONFIG_DM_I2C_COMPAT is not set
>> +# CONFIG_CROS_EC_KEYB is not set
>> +
>> +#
>> +# LED Support
>> +#
>> +# CONFIG_LED is not set
>> +
>> +#
>> +# Multifunction device drivers
>> +#
>> +# CONFIG_MISC is not set
>> +# CONFIG_CROS_EC is not set
>> +# CONFIG_FSL_SEC_MON is not set
>> +# CONFIG_MXC_OCOTP is not set
>> +# CONFIG_PCA9551_LED is not set
>> +# CONFIG_RESET is not set
>> +
>> +#
>> +# MMC Host controller Support
>> +#
>> +# CONFIG_DM_MMC is not set
>> +
>> +#
>> +# MTD Support
>> +#
>> +# CONFIG_MTD is not set
>> +
>> +#
>> +# NAND Device Support
>> +#
>> +# CONFIG_NAND_DENALI is not set
>> +# CONFIG_NAND_VF610_NFC is not set
>> +# CONFIG_NAND_PXA3XX is not set
>> +
>> +#
>> +# Generic NAND options
>> +#
>> +
>> +#
>> +# SPI Flash Support
>> +#
>> +# CONFIG_SPI_FLASH is not set
>> +# CONFIG_DM_ETH is not set
>> +# CONFIG_PHYLIB is not set
>> +
>> +#
>> +# PCI
>> +#
>> +# CONFIG_DM_PCI is not set
>> +
>> +#
>> +# Pin controllers
>> +#
>> +CONFIG_PINCTRL=y
>> +# CONFIG_PINCTRL_FULL is not set
>> +# CONFIG_ROCKCHIP_PINCTRL is not set
>> +# CONFIG_ROCKCHIP_3036_PINCTRL is not set
>> +CONFIG_PIC32_PINCTRL=y
>> +
>> +#
>> +# Power
>> +#
>> +# CONFIG_DM_PMIC is not set
>> +# CONFIG_DM_REGULATOR is not set
>> +# CONFIG_RAM is not set
>> +
>> +#
>> +# Remote Processor drivers
>> +#
>> +
>> +#
>> +# Real Time Clock
>> +#
>> +# CONFIG_DM_RTC is not set
>> +
>> +#
>> +# Serial drivers
>> +#
>> +CONFIG_REQUIRE_SERIAL_CONSOLE=y
>> +# CONFIG_DEBUG_UART is not set
>> +# CONFIG_ALTERA_JTAG_UART is not set
>> +# CONFIG_ALTERA_UART is not set
>> +# CONFIG_SYS_NS16550 is not set
>> +CONFIG_PIC32_SERIAL=y
>> +
>> +#
>> +# Sound support
>> +#
>> +# CONFIG_SOUND is not set
>> +
>> +#
>> +# SPI Support
>> +#
>> +# CONFIG_FSL_ESPI is not set
>> +# CONFIG_TI_QSPI is not set
>> +# CONFIG_DM_THERMAL is not set
>> +
>> +#
>> +# Timer Support
>> +#
>> +# CONFIG_TIMER is not set
>> +
>> +#
>> +# TPM support
>> +#
>> +# CONFIG_USB is not set
>> +
>> +#
>> +# Graphics support
>> +#
>> +# CONFIG_VIDEO_VESA is not set
>> +# CONFIG_VIDEO_LCD_ANX9804 is not set
>> +# CONFIG_VIDEO_LCD_SSD2828 is not set
>> +# CONFIG_DISPLAY_PORT is not set
>> +# CONFIG_VIDEO_TEGRA124 is not set
>> +# CONFIG_VIDEO_BRIDGE is not set
>> +# CONFIG_PHYS_TO_BUS is not set
>> +
>> +#
>> +# File systems
>> +#
>> +
>> +#
>> +# Library routines
>> +#
>> +# CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED is not set
>> +CONFIG_HAVE_PRIVATE_LIBGCC=y
>> +# CONFIG_USE_PRIVATE_LIBGCC is not set
>> +CONFIG_SYS_HZ=1000
>> +CONFIG_SYS_VSNPRINTF=y
>> +CONFIG_USE_TINY_PRINTF=y
>> +CONFIG_REGEX=y
>> +# CONFIG_LIB_RAND is not set
>> +CONFIG_CMD_DHRYSTONE=y
>> +# CONFIG_RSA is not set
>> +# CONFIG_TPM is not set
>> +
>> +#
>> +# Hashing Support
>> +#
>> +# CONFIG_SHA1 is not set
>> +# CONFIG_SHA256 is not set
>> +# CONFIG_SHA_HW_ACCEL is not set
>> +
>> +#
>> +# Compression Support
>> +#
>> +# CONFIG_LZ4 is not set
>> +# CONFIG_ERRNO_STR is not set
>> +# CONFIG_UNIT_TEST is not set
>> diff --git a/include/configs/pic32mzdask.h
>> b/include/configs/pic32mzdask.h
>> new file mode 100644
>> index 0000000..6552fa2
>> --- /dev/null
>> +++ b/include/configs/pic32mzdask.h
>> @@ -0,0 +1,94 @@
>> +/*
>> + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
>> + *
>> + * SPDX-License-Identifier:	GPL-2.0+
>> + *
>> + * Microchip PIC32MZ[DA] Starter Kit.
>> + */
>> +
>> +#ifndef __PIC32MZDASK_CONFIG_H
>> +#define __PIC32MZDASK_CONFIG_H
>> +
>> +/* System Configuration */
>> +#define CONFIG_SYS_TEXT_BASE		0x9d004000 /* .text */
>> +#define CONFIG_DISPLAY_BOARDINFO
>> +
>> +/*--------------------------------------------
>> + * CPU configuration
>> + */
>> +/* CPU Timer rate */
>> +#define CONFIG_SYS_MIPS_TIMER_FREQ	100000000
>> +
>> +/* Cache Configuration */
>> +#define CONFIG_SYS_MIPS_CACHE_MODE	CONF_CM_CACHABLE_NONCOHERE
>> NT
>> +
>> +/*------------------------------------------------------------------
>> ----
>> + * Memory Layout
>> + */
>> +#define CONFIG_SYS_SRAM_BASE		0x80000000
>> +#define CONFIG_SYS_SRAM_SIZE		0x00080000 /* 512K */
>> +
>> +/* Initial RAM for temporary stack, global data */
>> +#define CONFIG_SYS_INIT_RAM_SIZE	0x10000
>> +#define CONFIG_SYS_INIT_RAM_ADDR	\
>> +	(CONFIG_SYS_SRAM_BASE + CONFIG_SYS_SRAM_SIZE -
>> CONFIG_SYS_INIT_RAM_SIZE)
>> +#define CONFIG_SYS_INIT_SP_ADDR		\
>> +	(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE - 1)
>> +
>> +/* SDRAM Configuration (for final code, data, stack, heap) */
>> +#define CONFIG_SYS_SDRAM_BASE		0x88000000
>> +#define CONFIG_SYS_MALLOC_LEN		(256 << 10)
>> +#define CONFIG_SYS_BOOTPARAMS_LEN	(4 << 10)
>> +#define CONFIG_STACKSIZE		(4 << 10) /* regular stack
>> */
>> +
>> +#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE
>> +#define CONFIG_SYS_MONITOR_LEN		(192 << 10)
>> +
>> +#define CONFIG_SYS_LOAD_ADDR		0x88500000 /* default
>> load address */
>> +#define CONFIG_SYS_ENV_ADDR		0x88300000
>> +
>> +/* Memory Test */
>> +#define CONFIG_SYS_MEMTEST_START	0x88000000
>> +#define CONFIG_SYS_MEMTEST_END		0x88080000
>> +
>> +/*------------------------------------------------------------------
>> ----
>> + * Commands
>> + */
>> +#define CONFIG_SYS_LONGHELP		/* undef to save memory
>> */
>> +#define CONFIG_CMD_CLK
>> +
>> +/*-------------------------------------------------
>> + * FLASH configuration
>> + */
>> +#define CONFIG_SYS_NO_FLASH
>> +
>> +/*------------------------------------------------------------
>> + * Console Configuration
>> + */
>> +#define CONFIG_BAUDRATE			115200
>> +#define CONFIG_SYS_BAUDRATE_TABLE	{9600, 19200, 38400, 57600,
>> 115200}
>> +#define CONFIG_SYS_CBSIZE		1024 /* Console I/O Buffer
>> Size   */
>> +#define CONFIG_SYS_MAXARGS		16   /* max number of
>> command args*/
>> +#define CONFIG_SYS_PBSIZE		\
>> +		(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
>> +#define CONFIG_CMDLINE_EDITING		1
>> +
>> +/*
>> + * Handover flattened device tree (dtb file) to Linux kernel
>> + */
>> +#define CONFIG_OF_LIBFDT	1
>> +
>> +/* -------------------------------------------------
>> + * Environment
>> + */
>> +#define CONFIG_ENV_IS_NOWHERE	1
>> +#define CONFIG_ENV_SIZE		0x4000
>> +
>> +/* -----------------------------------------------------------------
>> ----
>> + * Board boot configuration
>> + */
>> +#define CONFIG_TIMESTAMP	/* Print image info with timestamp
>> */
>> +#define CONFIG_BOOTDELAY	5 /* autoboot after X seconds     */
>> +#undef	CONFIG_BOOTARGS
>> +
>> +#endif	/* __PIC32MZDASK_CONFIG_H */

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 10/14] drivers: mmc: add driver for Microchip PIC32 SDHCI controller.
  2016-01-13 15:15   ` Daniel Schwierzeck
@ 2016-01-14  9:18     ` Purna Chandra Mandal
  0 siblings, 0 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-14  9:18 UTC (permalink / raw)
  To: u-boot

On 01/13/2016 08:45 PM, Daniel Schwierzeck wrote:
> Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra Mandal:
>> From: Andrei Pistirica <andrei.pistirica@microchip.com>
>>
>> This driver implements platform specific glue and fixups for
>> PIC32 internal SDHCI controller.
>>
>> Signed-off-by: Andrei Pistirica <andrei.pistirica@microchip.com>
>> Signed-off-by: Sandeep Sheriker Mallikarjun <
>> sandeepsheriker.mallikarjun at microchip.com>
>> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
>>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
>
> nits below
>
>> ---
>>
>> Changes in v3:
>> - remove ofdata_to_platdata, and replace platdata with priv
>> - replace pic32_ioremap() with ioremap()
>>
>> Changes in v2:
>> - drop sdhci shared bus configuration (for shared interrupt, clock
>> pins)
>>
>>  drivers/mmc/Kconfig       |  6 +++++
>>  drivers/mmc/Makefile      |  2 +-
>>  drivers/mmc/pic32_sdhci.c | 61
>> +++++++++++++++++++++++++++++++++++++++++++++++
>>  drivers/mmc/sdhci.c       | 12 ++++++++++
>>  4 files changed, 80 insertions(+), 1 deletion(-)
>>  create mode 100644 drivers/mmc/pic32_sdhci.c
>>
>> diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
>> index ceae7bc..0b6f54b 100644
>> --- a/drivers/mmc/Kconfig
>> +++ b/drivers/mmc/Kconfig
>> @@ -31,4 +31,10 @@ config SH_SDHI
>>  	help
>>  	  Support for the on-chip SDHI host controller on
>> SuperH/Renesas ARM SoCs platform
>>  
>> +config PIC32_SDHCI
>> +	bool "Microchip PIC32 on-chip SDHCI support"
>> +	depends on DM_MMC && MACH_PIC32
>> +	help
>> +	  Support for the on-chip SDHCI support on Microchip PIC32
>> platforms.
>> +
>>  endmenu
>> diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
>> index 5d35705..c9c3e3e 100644
>> --- a/drivers/mmc/Makefile
>> +++ b/drivers/mmc/Makefile
>> @@ -48,4 +48,4 @@ obj-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o
>>  else
>>  obj-$(CONFIG_GENERIC_MMC) += mmc_write.o
>>  endif
>> -
>> +obj-$(CONFIG_PIC32_SDHCI) += pic32_sdhci.o
>> diff --git a/drivers/mmc/pic32_sdhci.c b/drivers/mmc/pic32_sdhci.c
>> new file mode 100644
>> index 0000000..f8a5a23
>> --- /dev/null
>> +++ b/drivers/mmc/pic32_sdhci.c
>> @@ -0,0 +1,61 @@
>> +/*
>> + * Support of SDHCI for Microchip PIC32 SoC.
>> + *
>> + * Copyright (C) 2015 Microchip Technology Inc.
>> + * Andrei Pistirica <andrei.pistirica@microchip.com>
>> + *
>> + * SPDX-License-Identifier:	GPL-2.0+
>> + */
>> +
>> +#include <dm.h>
>> +#include <common.h>
>> +#include <sdhci.h>
>> +#include <asm/errno.h>
>> +#include <mach/pic32.h>
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +static int pic32_sdhci_probe(struct udevice *dev)
>> +{
>> +	struct sdhci_host *host = dev_get_priv(dev);
>> +	const void *fdt = gd->fdt_blob;
>> +	u32 f_min_max[2];
>> +	fdt_addr_t addr;
>> +	fdt_size_t size;
>> +	int ret;
>> +
>> +	addr = fdtdec_get_addr_size(fdt, dev->of_offset, "reg",
>> &size);
>> +	if (addr == FDT_ADDR_T_NONE)
>> +		return -EINVAL;
>> +
>> +	host->ioaddr = ioremap(addr, size);
>> +	if (!host->ioaddr)
>> +		return -EINVAL;
> this check can be dropped. ioremap() always returns a mapped address

Ack. Will drop.

>> +
>> +	host->name	= (char *)dev->name;
>> +	host->quirks	= SDHCI_QUIRK_NO_HISPD_BIT;
>> +	host->bus_width	= fdtdec_get_int(gd->fdt_blob, dev
>> ->of_offset,
>> +					"bus-width", 4);
>> +
>> +	ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
>> +				   "clock-freq-min-max", f_min_max,
>> 2);
>> +	if (ret) {
>> +		printf("sdhci: clock-freq-min-max not found\n");
>> +		return ret;
>> +	}
>> +
>> +	return add_sdhci(host, f_min_max[1], f_min_max[0]);
>> +}
>> +
>> +static const struct udevice_id pic32_sdhci_ids[] = {
>> +	{ .compatible = "microchip,pic32mzda-sdhci" },
>> +	{ }
>> +};
>> +
>> +U_BOOT_DRIVER(pic32_sdhci_drv) = {
>> +	.name			= "pic32_sdhci",
>> +	.id			= UCLASS_MMC,
>> +	.of_match		= pic32_sdhci_ids,
>> +	.probe			= pic32_sdhci_probe,
>> +	.priv_auto_alloc_size	= sizeof(struct sdhci_host),
>> +};
>> diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
>> index 02d71b9..f32fe67 100644
>> --- a/drivers/mmc/sdhci.c
>> +++ b/drivers/mmc/sdhci.c
>> @@ -424,6 +424,18 @@ static void sdhci_set_ios(struct mmc *mmc)
>>  	if (host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)
>>  		ctrl &= ~SDHCI_CTRL_HISPD;
>>  
>> +#if defined(CONFIG_PIC32_SDHCI)
>> +	/*
>> +	* In PIC32MZ[DA] due to h/w bug SDHCI fails detecting card
>> when JTAG
>> +	* is not connected.
>> +	* To work-around this problem:
>> +	*  - set Card_Detect_Signal_Selection bit in
>> SDHCI_Host_Control register
>> +	*  - clear Card_Detect_Test_Level bit in SDHCI_Host_Control
>> register
>> +	*/
>> +	ctrl |= SDHCI_CTRL_CD_TEST;
>> +	ctrl &= ~SDHCI_CTRL_CD_TEST_INS;
>> +#endif
> I think this could (or should?) be implemented with a new quirks bit

Will add new quirk (SDHCI_QUIRK_TEST_CD) to force CARD_PRESENT using TEST signals.
It will even help <board>.dts to disable/enable based on its device-tree property.

>> +
>>  	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
>>  }
>>  

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 13/14] drivers: net: Add ethernet driver for Microchip PIC32.
  2016-01-13 15:37   ` Daniel Schwierzeck
@ 2016-01-14 10:05     ` Purna Chandra Mandal
  2016-01-14 14:01       ` Daniel Schwierzeck
  0 siblings, 1 reply; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-14 10:05 UTC (permalink / raw)
  To: u-boot

On 01/13/2016 09:07 PM, Daniel Schwierzeck wrote:

> Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra Mandal:
>> This driver implements MAC and MII layer of the ethernet controller.
>> Network data transfer is handled by controller internal DMA engine.
>> Ethernet controller is configurable through device-tree file.
>>
>> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
>>
>>
>> ---
>>
>> Changes in v3:
>> - merge wrappers with eth operation callbacks
>> - read phy address from device-tree
>> - rename functions (e.g. _eth_xyz() with pic32_eth_xyz())
>>
>> Changes in v2: None
>>
>>  drivers/net/Kconfig      |   7 +
>>  drivers/net/Makefile     |   1 +
>>  drivers/net/pic32_eth.c  | 606
>> +++++++++++++++++++++++++++++++++++++++++++++++
>>  drivers/net/pic32_eth.h  | 171 +++++++++++++
>>  drivers/net/pic32_mdio.c | 121 ++++++++++
>>  5 files changed, 906 insertions(+)
>>  create mode 100644 drivers/net/pic32_eth.c
>>  create mode 100644 drivers/net/pic32_eth.h
>>  create mode 100644 drivers/net/pic32_mdio.c
>>
>> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
>> index ae5e78d..dc49493 100644
>> --- a/drivers/net/Kconfig
>> +++ b/drivers/net/Kconfig
>> @@ -108,4 +108,11 @@ config ZYNQ_GEM
>>  	help
>>  	  This MAC is present in Xilinx Zynq and ZynqMP SoCs.
>>  
>> +config PIC32_ETH
>> +	bool "Microchip PIC32 Ethernet Support"
>> +	depends on MACH_PIC32
> should be
>
> depends on DM_ETH && MACH_PIC32
> select PHYLIB

ack.

>> +	help
>> +	  This driver implements 10/100 Mbps Ethernet and MAC layer
>> for
>> +	  Microchip PIC32 microcontrollers.
>> +
>>  endif # NETDEVICES
>> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
>> index 150470c..33a81ee 100644
>> --- a/drivers/net/Makefile
>> +++ b/drivers/net/Makefile
>> @@ -72,3 +72,4 @@ obj-$(CONFIG_FSL_MC_ENET) += fsl-mc/
>>  obj-$(CONFIG_FSL_MC_ENET) += ldpaa_eth/
>>  obj-$(CONFIG_FSL_MEMAC) += fm/memac_phy.o
>>  obj-$(CONFIG_VSC9953) += vsc9953.o
>> +obj-$(CONFIG_PIC32_ETH) += pic32_mdio.o pic32_eth.o
>> diff --git a/drivers/net/pic32_eth.c b/drivers/net/pic32_eth.c
>> new file mode 100644
>> index 0000000..1cef62e
>> --- /dev/null
>> +++ b/drivers/net/pic32_eth.c
>> @@ -0,0 +1,606 @@
>> +/*
>> + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
>> + *
>> + * SPDX-License-Identifier:	GPL-2.0+
>> + *
>> + */
>> +#include <common.h>
>> +#include <errno.h>
>> +#include <dm.h>
>> +#include <net.h>
>> +#include <miiphy.h>
>> +#include <console.h>
>> +#include <wait_bit.h>
>> +#include <asm/gpio.h>
>> +
>> +#include "pic32_eth.h"
>> +
>> +#define MAX_RX_BUF_SIZE		1536
>> +#define MAX_RX_DESCR		PKTBUFSRX
>> +#define MAX_TX_DESCR		2
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +struct pic32eth_dev {
>> +	struct eth_dma_desc rxd_ring[MAX_RX_DESCR];
>> +	struct eth_dma_desc txd_ring[MAX_TX_DESCR];
>> +	u32 rxd_idx; /* index of RX desc to read */
>> +	/* regs */
>> +	struct pic32_ectl_regs *ectl_regs;
>> +	struct pic32_emac_regs *emac_regs;
>> +	/* Phy */
>> +	struct phy_device *phydev;
>> +	phy_interface_t phyif;
>> +	u32 phy_addr;
>> +	struct gpio_desc rst_gpio;
>> +};
>> +
>> +void __weak board_netphy_reset(void *dev)
>> +{
>> +	struct pic32eth_dev *priv = (struct pic32eth_dev *)dev;
> the cast is not necessary

ack. Will remove,

>> +
>> +	if (!dm_gpio_is_valid(&priv->rst_gpio))
>> +		return;
>> +
>> +	/* phy reset */
>> +	dm_gpio_set_value(&priv->rst_gpio, 0);
>> +	udelay(300);
>> +	dm_gpio_set_value(&priv->rst_gpio, 1);
>> +	udelay(300);
>> +}
>> +
>> +/* Initialize mii(MDIO) interface, discover which PHY is
>> + * attached to the device, and configure it properly.
>> + */
>> +static int pic32_mii_init(struct pic32eth_dev *priv)
>> +{
>> +	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
>> +	struct pic32_emac_regs *emac_p = priv->emac_regs;
>> +
>> +	/* board phy reset */
>> +	board_netphy_reset(priv);
>> +
>> +	/* disable RX, TX & all transactions */
>> +	writel(ETHCON_ON | ETHCON_TXRTS | ETHCON_RXEN, &ectl_p
>> ->con1.clr);
>> +
>> +	/* wait till busy */
>> +	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY,
>> false,
>> +		     CONFIG_SYS_HZ, false);
>> +
>> +	/* turn controller ON to access PHY over MII */
>> +	writel(ETHCON_ON, &ectl_p->con1.set);
>> +
>> +	mdelay(10);
>> +
>> +	/* reset MAC */
>> +	writel(EMAC_SOFTRESET, &emac_p->cfg1.set); /* reset assert
>> */
>> +	mdelay(10);
>> +	writel(EMAC_SOFTRESET, &emac_p->cfg1.clr); /* reset deassert
>> */
>> +
>> +	/* initialize MDIO/MII */
>> +	if (priv->phyif == PHY_INTERFACE_MODE_RMII) {
>> +		writel(EMAC_RMII_RESET, &emac_p->supp.set);
>> +		mdelay(10);
>> +		writel(EMAC_RMII_RESET, &emac_p->supp.clr);
>> +	}
>> +
>> +	return pic32_mdio_init(PIC32_MDIO_NAME, (ulong)&emac_p
>> ->mii);
>> +}
>> +
>> +static int pic32_phy_init(struct pic32eth_dev *priv, struct udevice
>> *dev)
>> +{
>> +	struct mii_dev *mii;
>> +
>> +	mii = miiphy_get_dev_by_name(PIC32_MDIO_NAME);
>> +
>> +	/* find & connect PHY */
>> +	priv->phydev = phy_connect(mii, priv->phy_addr,
>> +				   dev, priv->phyif);
>> +	if (!priv->phydev) {
>> +		printf("%s: %s: Error, PHY connect\n", __FILE__,
>> __func__);
>> +		return 0;
>> +	}
>> +
>> +	/* Wait for phy to complete reset */
>> +	mdelay(10);
>> +
>> +	/* configure supported modes */
>> +	priv->phydev->supported = SUPPORTED_10baseT_Half |
>> +				  SUPPORTED_10baseT_Full |
>> +				  SUPPORTED_100baseT_Half |
>> +				  SUPPORTED_100baseT_Full |
>> +				  SUPPORTED_Autoneg;
>> +
>> +	priv->phydev->advertising = ADVERTISED_10baseT_Half |
>> +				    ADVERTISED_10baseT_Full |
>> +				    ADVERTISED_100baseT_Half |
>> +				    ADVERTISED_100baseT_Full |
>> +				    ADVERTISED_Autoneg;
>> +
>> +	priv->phydev->autoneg = AUTONEG_ENABLE;
>> +
>> +	return 0;
>> +}
>> +
>> +/* Configure MAC based on negotiated speed and duplex
>> + * reported by PHY.
>> + */
>> +static int pic32_mac_adjust_link(struct pic32eth_dev *priv)
>> +{
>> +	struct phy_device *phydev = priv->phydev;
>> +	struct pic32_emac_regs *emac_p = priv->emac_regs;
>> +
>> +	if (!phydev->link) {
>> +		printf("%s: No link.\n", phydev->dev->name);
>> +		return -EINVAL;
>> +	}
>> +
>> +	if (phydev->duplex) {
>> +		writel(EMAC_FULLDUP, &emac_p->cfg2.set);
>> +		writel(FULLDUP_GAP_TIME, &emac_p->ipgt.raw);
>> +	} else {
>> +		writel(EMAC_FULLDUP, &emac_p->cfg2.clr);
>> +		writel(HALFDUP_GAP_TIME, &emac_p->ipgt.raw);
>> +	}
>> +
>> +	switch (phydev->speed) {
>> +	case SPEED_100:
>> +		writel(EMAC_RMII_SPD100, &emac_p->supp.set);
>> +		break;
>> +	case SPEED_10:
>> +		writel(EMAC_RMII_SPD100, &emac_p->supp.clr);
>> +		break;
>> +	default:
>> +		printf("%s: Speed was bad\n", phydev->dev->name);
>> +		return -EINVAL;
>> +	}
>> +
>> +	printf("pic32eth: PHY is %s with %dbase%s, %s\n",
>> +	       phydev->drv->name, phydev->speed,
>> +	       (phydev->port == PORT_TP) ? "T" : "X",
>> +	       (phydev->duplex) ? "full" : "half");
>> +
>> +	return 0;
>> +}
>> +
>> +static void pic32_mac_init(struct pic32eth_dev *priv, u8 *macaddr)
>> +{
>> +	struct pic32_emac_regs *emac_p = priv->emac_regs;
>> +	u32 stat = 0, v;
>> +	u64 expire;
>> +
>> +	v = EMAC_TXPAUSE | EMAC_RXPAUSE | EMAC_RXENABLE;
>> +	writel(v, &emac_p->cfg1.raw);
>> +
>> +	v = EMAC_EXCESS | EMAC_AUTOPAD | EMAC_PADENABLE |
>> +	    EMAC_CRCENABLE | EMAC_LENGTHCK | EMAC_FULLDUP;
>> +	writel(v, &emac_p->cfg2.raw);
>> +
>> +	/* recommended back-to-back inter-packet gap for 10 Mbps
>> half duplex */
>> +	writel(HALFDUP_GAP_TIME, &emac_p->ipgt.raw);
>> +
>> +	/* recommended non-back-to-back interpacket gap is 0xc12 */
>> +	writel(0xc12, &emac_p->ipgr.raw);
>> +
>> +	/* recommended collision window retry limit is 0x370F */
>> +	writel(0x370f, &emac_p->clrt.raw);
>> +
>> +	/* set maximum frame length: allow VLAN tagged frame */
>> +	writel(0x600, &emac_p->maxf.raw);
>> +
>> +	/* set the mac address */
>> +	writel(macaddr[0] | (macaddr[1] << 8), &emac_p->sa2.raw);
>> +	writel(macaddr[2] | (macaddr[3] << 8), &emac_p->sa1.raw);
>> +	writel(macaddr[4] | (macaddr[5] << 8), &emac_p->sa0.raw);
>> +
>> +	/* default, enable 10 Mbps operation */
>> +	writel(EMAC_RMII_SPD100, &emac_p->supp.clr);
>> +
>> +	/* wait until link status UP or deadline elapsed */
>> +	expire = get_ticks() + get_tbclk() * 2;
>> +	for (; get_ticks() < expire;) {
>> +		stat = phy_read(priv->phydev, priv->phy_addr,
>> MII_BMSR);
>> +		if (stat & BMSR_LSTATUS)
>> +			break;
>> +	}
>> +
>> +	if (!(stat & BMSR_LSTATUS))
>> +		printf("MAC: Link is DOWN!\n");
>> +
>> +	/* delay to stabilize before any tx/rx */
>> +	mdelay(10);
>> +}
>> +
>> +static void pic32_mac_reset(struct pic32eth_dev *priv)
>> +{
>> +	struct pic32_emac_regs *emac_p = priv->emac_regs;
>> +	struct mii_dev *mii;
>> +
>> +	/* Reset MAC */
>> +	writel(EMAC_SOFTRESET, &emac_p->cfg1.raw);
>> +	mdelay(10);
>> +
>> +	/* clear reset */
>> +	writel(0, &emac_p->cfg1.raw);
>> +
>> +	/* Reset MII */
>> +	mii = priv->phydev->bus;
>> +	if (mii && mii->reset)
>> +		mii->reset(mii);
>> +}
>> +
>> +/* initializes the MAC and PHY, then establishes a link */
>> +static void pic32_ctrl_reset(struct pic32eth_dev *priv)
>> +{
>> +	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
>> +	u32 v;
>> +
>> +	/* disable RX, TX & any other transactions */
>> +	writel(ETHCON_ON | ETHCON_TXRTS | ETHCON_RXEN, &ectl_p
>> ->con1.clr);
>> +
>> +	/* wait till busy */
>> +	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY,
>> false,
>> +		     CONFIG_SYS_HZ, false);
>> +	/* decrement received buffcnt to zero. */
>> +	while (readl(&ectl_p->stat.raw) & ETHSTAT_BUFCNT)
>> +		writel(ETHCON_BUFCDEC, &ectl_p->con1.set);
>> +
>> +	/* clear any existing interrupt event */
>> +	writel(0xffffffff, &ectl_p->irq.clr);
>> +
>> +	/* clear RX/TX start address */
>> +	writel(0xffffffff, &ectl_p->txst.clr);
>> +	writel(0xffffffff, &ectl_p->rxst.clr);
>> +
>> +	/* clear the receive filters */
>> +	writel(0x00ff, &ectl_p->rxfc.clr);
>> +
>> +	/* set the receive filters
>> +	 * ETH_FILT_CRC_ERR_REJECT
>> +	 * ETH_FILT_RUNT_REJECT
>> +	 * ETH_FILT_UCAST_ACCEPT
>> +	 * ETH_FILT_MCAST_ACCEPT
>> +	 * ETH_FILT_BCAST_ACCEPT
>> +	 */
>> +	v = ETHRXFC_BCEN | ETHRXFC_MCEN | ETHRXFC_UCEN |
>> +	    ETHRXFC_RUNTEN | ETHRXFC_CRCOKEN;
>> +	writel(v, &ectl_p->rxfc.set);
>> +
>> +	/* turn controller ON to access PHY over MII */
>> +	writel(ETHCON_ON, &ectl_p->con1.set);
>> +}
>> +
>> +static void pic32_rx_desc_init(struct pic32eth_dev *priv)
>> +{
>> +	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
>> +	struct eth_dma_desc *rxd;
>> +	u32 idx, bufsz;
>> +
>> +	priv->rxd_idx = 0;
>> +	for (idx = 0; idx < MAX_RX_DESCR; idx++) {
>> +		rxd = &priv->rxd_ring[idx];
>> +
>> +		/* hw owned */
>> +		rxd->hdr = EDH_NPV | EDH_EOWN | EDH_STICKY;
>> +
>> +		/* packet buffer address */
>> +		rxd->data_buff = virt_to_phys(net_rx_packets[idx]);
>> +
>> +		/* link to next desc */
>> +		rxd->next_ed = virt_to_phys(rxd + 1);
>> +
>> +		/* reset status */
>> +		rxd->stat1 = 0;
>> +		rxd->stat2 = 0;
>> +
>> +		/* decrement bufcnt */
>> +		writel(ETHCON_BUFCDEC, &ectl_p->con1.set);
>> +	}
>> +
>> +	/* link last descr to beginning of list */
>> +	rxd->next_ed = virt_to_phys(&priv->rxd_ring[0]);
>> +
>> +	/* flush rx ring */
>> +	__dcache_flush(priv->rxd_ring, sizeof(priv->rxd_ring));
>> +
>> +	/* set rx desc-ring start address */
>> +	writel((ulong)virt_to_phys(&priv->rxd_ring[0]), &ectl_p
>> ->rxst.raw);
>> +
>> +	/* RX Buffer size */
>> +	bufsz = readl(&ectl_p->con2.raw);
>> +	bufsz &= ~(ETHCON_RXBUFSZ << ETHCON_RXBUFSZ_SHFT);
>> +	bufsz |= ((MAX_RX_BUF_SIZE / 16) << ETHCON_RXBUFSZ_SHFT);
>> +	writel(bufsz, &ectl_p->con2.raw);
>> +
>> +	/* enable the receiver in hardware which allows hardware
>> +	 * to DMA received pkts to the descriptor pointer address.
>> +	 */
>> +	writel(ETHCON_RXEN, &ectl_p->con1.set);
>> +}
>> +
>> +static int pic32_eth_start(struct udevice *dev)
>> +{
>> +	struct eth_pdata *pdata = dev_get_platdata(dev);
>> +	struct pic32eth_dev *priv = dev_get_priv(dev);
>> +
>> +	/* controller */
>> +	pic32_ctrl_reset(priv);
>> +
>> +	/* reset MAC */
>> +	pic32_mac_reset(priv);
>> +
>> +	/* configure PHY */
>> +	phy_config(priv->phydev);
>> +
>> +	/* initialize MAC */
>> +	pic32_mac_init(priv, &pdata->enetaddr[0]);
>> +
>> +	/* init RX descriptor; TX descriptors are handled in xmit */
>> +	pic32_rx_desc_init(priv);
>> +
>> +	/* Start up & update link status of PHY */
>> +	phy_startup(priv->phydev);
>> +
>> +	/* adjust mac with phy link status */
>> +	return pic32_mac_adjust_link(priv);
>> +}
>> +
>> +static void pic32_eth_stop(struct udevice *dev)
>> +{
>> +	struct pic32eth_dev *priv = dev_get_priv(dev);
>> +	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
>> +	struct pic32_emac_regs *emac_p = priv->emac_regs;
>> +
>> +	/* Reset the phy if the controller is enabled */
>> +	if (readl(&ectl_p->con1.raw) & ETHCON_ON)
>> +		phy_reset(priv->phydev);
>> +
>> +	/* Shut down the PHY */
>> +	phy_shutdown(priv->phydev);
>> +
>> +	/* Stop rx/tx */
>> +	writel(ETHCON_TXRTS | ETHCON_RXEN, &ectl_p->con1.clr);
>> +	mdelay(10);
>> +
>> +	/* reset MAC */
>> +	writel(EMAC_SOFTRESET, &emac_p->cfg1.raw);
>> +
>> +	/* clear reset */
>> +	writel(0, &emac_p->cfg1.raw);
>> +	mdelay(10);
>> +
>> +	/* disable controller */
>> +	writel(ETHCON_ON, &ectl_p->con1.clr);
>> +	mdelay(10);
>> +
>> +	/* wait until everything is down */
>> +	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY,
>> false,
>> +		     2 * CONFIG_SYS_HZ, false);
>> +
>> +	/* clear any existing interrupt event */
>> +	writel(0xffffffff, &ectl_p->irq.clr);
>> +}
>> +
>> +static int pic32_eth_send(struct udevice *dev, void *packet, int
>> length)
>> +{
>> +	struct pic32eth_dev *priv = dev_get_priv(dev);
>> +	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
>> +	struct eth_dma_desc *txd;
>> +	u64 deadline;
>> +
>> +	txd = &priv->txd_ring[0];
>> +
>> +	/* set proper flags & length in descriptor header */
>> +	txd->hdr = EDH_SOP | EDH_EOP | EDH_EOWN |
>> EDH_BCOUNT(length);
>> +
>> +	/* pass buffer address to hardware */
>> +	txd->data_buff = virt_to_phys(packet);
>> +
>> +	debug("%s: %d / .hdr %x, .data_buff %x, .stat %x, .nexted
>> %x\n",
>> +	      __func__, __LINE__, txd->hdr, txd->data_buff, txd
>> ->stat2,
>> +	      txd->next_ed);
>> +
>> +	/* cache flush (packet) */
>> +	__dcache_flush(packet, length);
>> +
>> +	/* cache flush (txd) */
>> +	__dcache_flush(txd, sizeof(*txd));
>> +
>> +	/* pass descriptor table base to h/w */
>> +	writel(virt_to_phys(txd), &ectl_p->txst.raw);
>> +
>> +	/* ready to send enabled, hardware can now send the
>> packet(s) */
>> +	writel(ETHCON_TXRTS | ETHCON_ON, &ectl_p->con1.set);
>> +
>> +	/* wait until tx has completed and h/w has released
>> ownership
>> +	 * of the tx descriptor or timeout elapsed.
>> +	 */
>> +	deadline = get_ticks() + get_tbclk();
>> +	for (;;) {
>> +		/* check timeout */
>> +		if (get_ticks() > deadline)
>> +			return -ETIMEDOUT;
>> +
>> +		if (ctrlc())
>> +			return -EINTR;
>> +
>> +		/* tx completed ? */
>> +		if (readl(&ectl_p->con1.raw) & ETHCON_TXRTS) {
>> +			udelay(1);
>> +			continue;
>> +		}
>> +
>> +		/* h/w not released ownership yet? */
>> +		__dcache_invalidate(txd, sizeof(*txd));
>> +		if (!(txd->hdr & EDH_EOWN))
>> +			break;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int pic32_eth_recv(struct udevice *dev, int flags, uchar
>> **packetp)
>> +{
>> +	struct pic32eth_dev *priv = dev_get_priv(dev);
>> +	struct eth_dma_desc *rxd;
>> +	u32 idx = priv->rxd_idx;
>> +	u32 rx_count;
>> +
>> +	/* find the next ready to receive */
>> +	rxd = &priv->rxd_ring[idx];
>> +
>> +	__dcache_invalidate(rxd, sizeof(*rxd));
>> +	/* check if owned by MAC */
>> +	if (rxd->hdr & EDH_EOWN)
>> +		return -EAGAIN;
>> +
>> +	/* Sanity check on header: SOP and EOP  */
>> +	if ((rxd->hdr & (EDH_SOP | EDH_EOP)) != (EDH_SOP | EDH_EOP))
>> {
>> +		printf("%s: %s, rx pkt across multiple descr\n",
>> +		       __FILE__, __func__);
>> +		return 0;
>> +	}
>> +
>> +	debug("%s: %d /idx %i, hdr=%x, data_buff %x, stat %x, nexted
>> %x\n",
>> +	      __func__, __LINE__, idx, rxd->hdr,
>> +	      rxd->data_buff, rxd->stat2, rxd->next_ed);
>> +
>> +	/* Sanity check on rx_stat: OK, CRC */
>> +	if (!RSV_RX_OK(rxd->stat2) || RSV_CRC_ERR(rxd->stat2)) {
>> +		debug("%s: %s: Error, rx problem detected\n",
>> +		      __FILE__, __func__);
>> +		return 0;
>> +	}
>> +
>> +	/* invalidate dcache */
>> +	rx_count = RSV_RX_COUNT(rxd->stat2);
>> +	__dcache_invalidate(net_rx_packets[idx], rx_count);
>> +
>> +	/* Pass the packet to protocol layer */
>> +	*packetp = net_rx_packets[idx];
>> +
>> +	/* increment number of bytes rcvd (ignore CRC) */
>> +	return rx_count - 4;
>> +}
>> +
>> +static int pic32_eth_free_pkt(struct udevice *dev, uchar *packet,
>> int length)
>> +{
>> +	struct pic32eth_dev *priv = dev_get_priv(dev);
>> +	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
>> +	struct eth_dma_desc *rxd;
>> +	int idx = priv->rxd_idx;
>> +
>> +	/* sanity check */
>> +	if (packet != net_rx_packets[idx]) {
>> +		printf("rxd_id %d: packet is not matched,\n", idx);
>> +		return -EAGAIN;
>> +	}
>> +
>> +	/* prepare for receive */
>> +	rxd = &priv->rxd_ring[idx];
>> +	rxd->hdr = EDH_STICKY | EDH_NPV | EDH_EOWN;
>> +
>> +	__dcache_flush(rxd, sizeof(*rxd));
>> +
>> +	/* decrement rx pkt count */
>> +	writel(ETHCON_BUFCDEC, &ectl_p->con1.set);
>> +
>> +	debug("%s: %d / idx %i, hdr %x, data_buff %x, stat %x,
>> nexted %x\n",
>> +	      __func__, __LINE__, idx, rxd->hdr, rxd->data_buff,
>> +	      rxd->stat2, rxd->next_ed);
>> +
>> +	priv->rxd_idx = (priv->rxd_idx + 1) % MAX_RX_DESCR;
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct eth_ops pic32_eth_ops = {
>> +	.start		= pic32_eth_start,
>> +	.send		= pic32_eth_send,
>> +	.recv		= pic32_eth_recv,
>> +	.free_pkt	= pic32_eth_free_pkt,
>> +	.stop		= pic32_eth_stop,
>> +};
>> +
>> +static int pic32_eth_probe(struct udevice *dev)
>> +{
>> +	struct eth_pdata *pdata = dev_get_platdata(dev);
> your driver private data should be stored in struct pic32eth_dev

Please see below.

>> +	struct pic32eth_dev *priv = dev_get_priv(dev);
>> +	const char *phy_mode;
>> +	void __iomem *iobase;
>> +	fdt_addr_t addr;
>> +	fdt_size_t size;
>> +	int offset = 0;
>> +	int phy_addr = -1;
>> +
>> +	addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset,
>> "reg", &size);
>> +	if (addr == FDT_ADDR_T_NONE)
>> +		return -EINVAL;
>> +
>> +	iobase = ioremap(addr, size);
>> +	if (!iobase)
>> +		return -EINVAL;
> you can drop this check. ioremap() always returns a mapped address.

ack.

>> +
>> +	pdata->iobase = (phys_addr_t)addr;
>> +
>> +	/* get phy mode */
>> +	pdata->phy_interface = -1;
>> +	phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy
>> -mode", NULL);
>> +	if (phy_mode)
>> +		pdata->phy_interface =
>> phy_get_interface_by_name(phy_mode);
>> +	if (pdata->phy_interface == -1) {
>> +		debug("%s: Invalid PHY interface '%s'\n", __func__,
>> phy_mode);
>> +		return -EINVAL;
>> +	}
> your driver private data should be stored in struct pic32eth_dev. Only
> if a arch/SoC does not support device-tree, platdata have to be
> initialized with PHY address and PHY interface in the board code. Also
> form a drivers point of view, platdata is read-only and provides board
> -specific configuration for the driver.

Please note here (as you pointed out earlier also) driver private data (as defined by struct pic32eth_dev) is maintained at priv field of udevice. This is sufficient for the driver to work.
On the other hand, u-boot network library expects 'struct eth_pdata' (as platdata) to be filled by the driver instance with correct information (like baseaddr, phy_interface, enetaddr). Network library uses this data structure to preprate, process (create-random-if-unset or download-from-some-storage-based-on-env or some else) and pass to the relevant ethernet device at different time as part of some callback. I have taken inspiration from other net drivers (drivers/net/).

>> +
>> +	/* get phy addr */
>> +	offset = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset,
>> +				       "phy-handle");
>> +	if (offset > 0)
>> +		phy_addr = fdtdec_get_int(gd->fdt_blob, offset,
>> "reg", -1);
>> +
>> +	/* phy reset gpio */
>> +	gpio_request_by_name_nodev(gd->fdt_blob, dev->of_offset,
>> +				   "reset-gpios", 0,
>> +				   &priv->rst_gpio, GPIOD_IS_OUT);
>> +
>> +	priv->phyif	= pdata->phy_interface;
>> +	priv->phy_addr	= phy_addr;
>> +	priv->ectl_regs	= iobase;
>> +	priv->emac_regs	= iobase + PIC32_EMAC1CFG1;
>> +
>> +	pic32_mii_init(priv);
>> +
>> +	return pic32_phy_init(priv, dev);
>> +}
>> +
>> +static int pic32_eth_remove(struct udevice *dev)
>> +{
>> +	struct pic32eth_dev *priv = dev_get_priv(dev);
>> +	struct mii_dev *bus;
>> +
>> +	dm_gpio_free(dev, &priv->rst_gpio);
>> +	phy_shutdown(priv->phydev);
>> +	free(priv->phydev);
>> +	bus = miiphy_get_dev_by_name(PIC32_MDIO_NAME);
>> +	mdio_unregister(bus);
>> +	mdio_free(bus);
>> +	iounmap(priv->ectl_regs);
>> +	return 0;
>> +}
>> +
>> +static const struct udevice_id pic32_eth_ids[] = {
>> +	{ .compatible = "microchip,pic32mzda-eth" },
>> +	{ }
>> +};
>> +
>> +U_BOOT_DRIVER(pic32_ethernet) = {
>> +	.name			= "pic32_ethernet",
>> +	.id			= UCLASS_ETH,
>> +	.of_match		= pic32_eth_ids,
>> +	.probe			= pic32_eth_probe,
>> +	.remove			= pic32_eth_remove,
>> +	.ops			= &pic32_eth_ops,
>> +	.priv_auto_alloc_size	= sizeof(struct pic32eth_dev),
>> +	.platdata_auto_alloc_size	= sizeof(struct eth_pdata),
>> +};
>> diff --git a/drivers/net/pic32_eth.h b/drivers/net/pic32_eth.h
>> new file mode 100644
>> index 0000000..4dd443b
>> --- /dev/null
>> +++ b/drivers/net/pic32_eth.h
>> @@ -0,0 +1,171 @@
>> +/*
>> + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
>> + *
>> + * SPDX-License-Identifier:	GPL-2.0+
>> + *
>> + */
>> +
>> +#ifndef __MICROCHIP_PIC32_ETH_H_
>> +#define __MICROCHIP_PIC32_ETH_H_
>> +
>> +#include <mach/pic32.h>
>> +
>> +/* Ethernet */
>> +struct pic32_ectl_regs {
>> +	struct pic32_reg_atomic con1; /* 0x00 */
>> +	struct pic32_reg_atomic con2; /* 0x10 */
>> +	struct pic32_reg_atomic txst; /* 0x20 */
>> +	struct pic32_reg_atomic rxst; /* 0x30 */
>> +	struct pic32_reg_atomic ht0;  /* 0x40 */
>> +	struct pic32_reg_atomic ht1;  /* 0x50 */
>> +	struct pic32_reg_atomic pmm0; /* 0x60 */
>> +	struct pic32_reg_atomic pmm1; /* 0x70 */
>> +	struct pic32_reg_atomic pmcs; /* 0x80 */
>> +	struct pic32_reg_atomic pmo;  /* 0x90 */
>> +	struct pic32_reg_atomic rxfc; /* 0xa0 */
>> +	struct pic32_reg_atomic rxwm; /* 0xb0 */
>> +	struct pic32_reg_atomic ien;  /* 0xc0 */
>> +	struct pic32_reg_atomic irq;  /* 0xd0 */
>> +	struct pic32_reg_atomic stat; /* 0xe0 */
>> +};
>> +
>> +struct pic32_mii_regs {
>> +	struct pic32_reg_atomic mcfg; /* 0x280 */
>> +	struct pic32_reg_atomic mcmd; /* 0x290 */
>> +	struct pic32_reg_atomic madr; /* 0x2a0 */
>> +	struct pic32_reg_atomic mwtd; /* 0x2b0 */
>> +	struct pic32_reg_atomic mrdd; /* 0x2c0 */
>> +	struct pic32_reg_atomic mind; /* 0x2d0 */
>> +};
>> +
>> +struct pic32_emac_regs {
>> +	struct pic32_reg_atomic cfg1; /* 0x200*/
>> +	struct pic32_reg_atomic cfg2; /* 0x210*/
>> +	struct pic32_reg_atomic ipgt; /* 0x220*/
>> +	struct pic32_reg_atomic ipgr; /* 0x230*/
>> +	struct pic32_reg_atomic clrt; /* 0x240*/
>> +	struct pic32_reg_atomic maxf; /* 0x250*/
>> +	struct pic32_reg_atomic supp; /* 0x260*/
>> +	struct pic32_reg_atomic test; /* 0x270*/
>> +	struct pic32_mii_regs mii;    /* 0x280 - 0x2d0 */
>> +	struct pic32_reg_atomic res1; /* 0x2e0 */
>> +	struct pic32_reg_atomic res2; /* 0x2f0 */
>> +	struct pic32_reg_atomic sa0;  /* 0x300 */
>> +	struct pic32_reg_atomic sa1;  /* 0x310 */
>> +	struct pic32_reg_atomic sa2;  /* 0x320 */
>> +};
>> +
>> +/* ETHCON1 Reg field */
>> +#define ETHCON_BUFCDEC		BIT(0)
>> +#define ETHCON_RXEN		BIT(8)
>> +#define ETHCON_TXRTS		BIT(9)
>> +#define ETHCON_ON		BIT(15)
>> +
>> +/* ETHCON2 Reg field */
>> +#define ETHCON_RXBUFSZ		0x7f
>> +#define ETHCON_RXBUFSZ_SHFT	0x4
>> +
>> +/* ETHSTAT Reg field */
>> +#define ETHSTAT_BUSY		BIT(7)
>> +#define ETHSTAT_BUFCNT		0x00ff0000
>> +
>> +/* ETHRXFC Register fields */
>> +#define ETHRXFC_BCEN		BIT(0)
>> +#define ETHRXFC_MCEN		BIT(1)
>> +#define ETHRXFC_UCEN		BIT(3)
>> +#define ETHRXFC_RUNTEN		BIT(4)
>> +#define ETHRXFC_CRCOKEN		BIT(5)
>> +
>> +/* EMAC1CFG1 register offset */
>> +#define PIC32_EMAC1CFG1		0x0200
>> +
>> +/* EMAC1CFG1 register fields */
>> +#define EMAC_RXENABLE		BIT(0)
>> +#define EMAC_RXPAUSE		BIT(2)
>> +#define EMAC_TXPAUSE		BIT(3)
>> +#define EMAC_SOFTRESET		BIT(15)
>> +
>> +/* EMAC1CFG2 register fields */
>> +#define EMAC_FULLDUP		BIT(0)
>> +#define EMAC_LENGTHCK		BIT(1)
>> +#define EMAC_CRCENABLE		BIT(4)
>> +#define EMAC_PADENABLE		BIT(5)
>> +#define EMAC_AUTOPAD		BIT(7)
>> +#define EMAC_EXCESS		BIT(14)
>> +
>> +/* EMAC1IPGT register magic */
>> +#define FULLDUP_GAP_TIME	0x15
>> +#define HALFDUP_GAP_TIME	0x12
>> +
>> +/* EMAC1SUPP register fields */
>> +#define EMAC_RMII_SPD100	BIT(8)
>> +#define EMAC_RMII_RESET		BIT(11)
>> +
>> +/* MII Management Configuration Register */
>> +#define MIIMCFG_RSTMGMT		BIT(15)
>> +#define MIIMCFG_CLKSEL_DIV40	0x0020	/* 100Mhz / 40 */
>> +
>> +/* MII Management Command Register */
>> +#define MIIMCMD_READ		BIT(0)
>> +#define MIIMCMD_SCAN		BIT(1)
>> +
>> +/* MII Management Address Register */
>> +#define MIIMADD_REGADDR		0x1f
>> +#define MIIMADD_REGADDR_SHIFT	0
>> +#define MIIMADD_PHYADDR_SHIFT	8
>> +
>> +/* MII Management Indicator Register */
>> +#define MIIMIND_BUSY		BIT(0)
>> +#define MIIMIND_NOTVALID	BIT(2)
>> +#define MIIMIND_LINKFAIL	BIT(3)
>> +
>> +/* Packet Descriptor */
>> +/* Received Packet Status */
>> +#define _RSV1_PKT_CSUM		0xffff
>> +#define _RSV2_CRC_ERR		BIT(20)
>> +#define _RSV2_LEN_ERR		BIT(21)
>> +#define _RSV2_RX_OK		BIT(23)
>> +#define _RSV2_RX_COUNT		0xffff
>> +
>> +#define RSV_RX_CSUM(__rsv1)	((__rsv1) & _RSV1_PKT_CSUM)
>> +#define RSV_RX_COUNT(__rsv2)	((__rsv2) & _RSV2_RX_COUNT)
>> +#define RSV_RX_OK(__rsv2)	((__rsv2) & _RSV2_RX_OK)
>> +#define RSV_CRC_ERR(__rsv2)	((__rsv2) & _RSV2_CRC_ERR)
>> +
>> +/* Ethernet Hardware Descriptor Header bits */
>> +#define EDH_EOWN		BIT(7)
>> +#define EDH_NPV			BIT(8)
>> +#define EDH_STICKY		BIT(9)
>> +#define _EDH_BCOUNT		0x07ff0000
>> +#define EDH_EOP			BIT(30)
>> +#define EDH_SOP			BIT(31)
>> +#define EDH_BCOUNT_SHIFT	16
>> +#define EDH_BCOUNT(len)		((len) << EDH_BCOUNT_SHIFT)
>> +
>> +/* Ethernet Hardware Descriptors
>> + * ref: PIC32 Family Reference Manual Table 35-7
>> + * This structure represents the layout of the DMA
>> + * memory shared between the CPU and the Ethernet
>> + * controller.
>> + */
>> +/* TX/RX DMA descriptor */
>> +struct eth_dma_desc {
>> +	u32 hdr;	/* header */
>> +	u32 data_buff;	/* data buffer address */
>> +	u32 stat1;	/* transmit/receive packet status */
>> +	u32 stat2;	/* transmit/receive packet status */
>> +	u32 next_ed;	/* next descriptor */
>> +};
>> +
>> +/* cache operation helper */
>> +#define __dcache_flush(__a, __l) \
>> +	flush_dcache_range((ulong)(__a),  ((__l) + (ulong)(__a)))
>> +
>> +#define __dcache_invalidate(__a, __l) \
>> +	invalidate_dcache_range((ulong)(__a),  ((__l) +
>> (ulong)(__a)))
>> +
>> +#define PIC32_MDIO_NAME "PIC32_EMAC"
>> +
>> +int pic32_mdio_init(const char *name, ulong ioaddr);
>> +
>> +#endif /* __MICROCHIP_PIC32_ETH_H_*/
>> diff --git a/drivers/net/pic32_mdio.c b/drivers/net/pic32_mdio.c
>> new file mode 100644
>> index 0000000..578fc96
>> --- /dev/null
>> +++ b/drivers/net/pic32_mdio.c
>> @@ -0,0 +1,121 @@
>> +/*
>> + * pic32_mdio.c: PIC32 MDIO/MII driver, part of pic32_eth.c.
>> + *
>> + * Copyright 2015 Microchip Inc.
>> + *	Purna Chandra Mandal <purna.mandal@microchip.com>
>> + *
>> + * SPDX-License-Identifier:	GPL-2.0+
>> + */
>> +#include <common.h>
>> +#include <phy.h>
>> +#include <miiphy.h>
>> +#include <errno.h>
>> +#include <wait_bit.h>
>> +#include <asm/io.h>
>> +#include "pic32_eth.h"
>> +
>> +static int pic32_mdio_write(struct mii_dev *bus,
>> +			    int addr, int dev_addr,
>> +			    int reg, u16 value)
>> +{
>> +	u32 v;
>> +	struct pic32_mii_regs *mii_regs = bus->priv;
>> +
>> +	/* Wait for the previous operation to finish */
>> +	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
>> +		     false, CONFIG_SYS_HZ, true);
>> +
>> +	/* Put phyaddr and regaddr into MIIMADD */
>> +	v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg &
>> MIIMADD_REGADDR);
>> +	writel(v, &mii_regs->madr.raw);
>> +
>> +	/* Initiate a write command */
>> +	writel(value, &mii_regs->mwtd.raw);
>> +
>> +	/* Wait 30 clock cycles for busy flag to be set */
>> +	udelay(12);
>> +
>> +	/* Wait for write to complete */
>> +	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
>> +		     false, CONFIG_SYS_HZ, true);
>> +
>> +	return 0;
>> +}
>> +
>> +static int pic32_mdio_read(struct mii_dev *bus, int addr, int
>> devaddr, int reg)
>> +{
>> +	u32 v;
>> +	struct pic32_mii_regs *mii_regs = bus->priv;
>> +
>> +	/* Wait for the previous operation to finish */
>> +	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
>> +		     false, CONFIG_SYS_HZ, true);
>> +
>> +	/* Put phyaddr and regaddr into MIIMADD */
>> +	v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg &
>> MIIMADD_REGADDR);
>> +	writel(v, &mii_regs->madr.raw);
>> +
>> +	/* Initiate a read command */
>> +	writel(MIIMCMD_READ, &mii_regs->mcmd.raw);
>> +
>> +	/* Wait 30 clock cycles for busy flag to be set */
>> +	udelay(12);
>> +
>> +	/* Wait for read to complete */
>> +	wait_for_bit(__func__, &mii_regs->mind.raw,
>> +		     MIIMIND_NOTVALID | MIIMIND_BUSY,
>> +		     false, CONFIG_SYS_HZ, false);
>> +
>> +	/* Clear the command register */
>> +	writel(0, &mii_regs->mcmd.raw);
>> +
>> +	/* Grab the value read from the PHY */
>> +	v = readl(&mii_regs->mrdd.raw);
>> +	return v;
>> +}
>> +
>> +static int pic32_mdio_reset(struct mii_dev *bus)
>> +{
>> +	struct pic32_mii_regs *mii_regs = bus->priv;
>> +
>> +	/* Reset MII (due to new addresses) */
>> +	writel(MIIMCFG_RSTMGMT, &mii_regs->mcfg.raw);
>> +
>> +	/* Wait for the operation to finish */
>> +	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
>> +		     false, CONFIG_SYS_HZ, true);
>> +
>> +	/* Clear reset bit */
>> +	writel(0, &mii_regs->mcfg);
>> +
>> +	/* Wait for the operation to finish */
>> +	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
>> +		     false, CONFIG_SYS_HZ, true);
>> +
>> +	/* Set the MII Management Clock (MDC) - no faster than 2.5
>> MHz */
>> +	writel(MIIMCFG_CLKSEL_DIV40, &mii_regs->mcfg.raw);
>> +
>> +	/* Wait for the operation to finish */
>> +	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
>> +		     false, CONFIG_SYS_HZ, true);
>> +	return 0;
>> +}
>> +
>> +int pic32_mdio_init(const char *name, ulong ioaddr)
>> +{
>> +	struct mii_dev *bus;
>> +
>> +	bus = mdio_alloc();
>> +	if (!bus) {
>> +		printf("Failed to allocate PIC32-MDIO bus\n");
>> +		return -ENOMEM;
>> +	}
>> +
>> +	bus->read = pic32_mdio_read;
>> +	bus->write = pic32_mdio_write;
>> +	bus->reset = pic32_mdio_reset;
>> +	strncpy(bus->name, name, sizeof(bus->name));
>> +	bus->priv = (void *)ioaddr;
>> +
>> +	return mdio_register(bus);
>> +}

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 05/14] drivers: gpio: add driver for Microchip PIC32 GPIO controller.
  2016-01-13 20:10   ` Simon Glass
@ 2016-01-14 10:15     ` Purna Chandra Mandal
  0 siblings, 0 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-14 10:15 UTC (permalink / raw)
  To: u-boot

On 01/14/2016 01:40 AM, Simon Glass wrote:

> Hi Puma,
>
> On 12 January 2016 at 03:18, Purna Chandra Mandal
> <purna.mandal@microchip.com> wrote:
>> In PIC32 GPIO controller is part of PIC32 pin controller.
>> PIC32 has ten independently programmable ports and each with multiple pins.
>> Each of these pins can be configured and used as GPIO, provided they
>> are not in use for other peripherals.
>>
>> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
>>
>> ---
>>
>> Changes in v3:
>> - add check on dev_get_addr()
>>
>> Changes in v2: None
>>
>>  drivers/gpio/Kconfig      |   7 ++
>>  drivers/gpio/Makefile     |   2 +-
>>  drivers/gpio/pic32_gpio.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 183 insertions(+), 1 deletion(-)
>>  create mode 100644 drivers/gpio/pic32_gpio.c
>>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> Just a few nits.
>
>> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
>> index e60e9fd..13e9a6a 100644
>> --- a/drivers/gpio/Kconfig
>> +++ b/drivers/gpio/Kconfig
>> @@ -83,4 +83,11 @@ config VYBRID_GPIO
>>         help
>>           Say yes here to support Vybrid vf610 GPIOs.
>>
>> +config PIC32_GPIO
>> +       bool "Microchip PIC32 GPIO driver"
>> +       depends on DM_GPIO
>> +       default y if MACH_PIC32
>> +       help
>> +         Say yes here to support Microchip PIC32 GPIOs.
>> +
>>  endmenu
>> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
>> index fb4fd25..845a6d4 100644
>> --- a/drivers/gpio/Makefile
>> +++ b/drivers/gpio/Makefile
>> @@ -46,4 +46,4 @@ obj-$(CONFIG_STM32_GPIO)      += stm32_gpio.o
>>  obj-$(CONFIG_ZYNQ_GPIO)                += zynq_gpio.o
>>  obj-$(CONFIG_VYBRID_GPIO)      += vybrid_gpio.o
>>  obj-$(CONFIG_HIKEY_GPIO)       += hi6220_gpio.o
>> -
>> +obj-$(CONFIG_PIC32_GPIO)       += pic32_gpio.o
>> diff --git a/drivers/gpio/pic32_gpio.c b/drivers/gpio/pic32_gpio.c
>> new file mode 100644
>> index 0000000..5b23af4
>> --- /dev/null
>> +++ b/drivers/gpio/pic32_gpio.c
>> @@ -0,0 +1,175 @@
>> +/*
>> + * Copyright (c) 2015 Microchip Technology Inc
>> + * Purna Chandra Mandal <purna.mandal@microchip.com>
>> + *
>> + * SPDX-License-Identifier:    GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <dm.h>
>> +#include <errno.h>
>> +#include <malloc.h>
>> +#include <asm/io.h>
>> +#include <asm/gpio.h>
>> +#include <linux/compat.h>
>> +#include <dt-bindings/gpio/gpio.h>
>> +#include <mach/pic32.h>
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +/* Peripheral Pin Control */
>> +struct pic32_reg_port {
>> +       struct pic32_reg_atomic ansel;
>> +       struct pic32_reg_atomic tris;
>> +       struct pic32_reg_atomic port;
>> +       struct pic32_reg_atomic lat;
>> +       struct pic32_reg_atomic open_drain;
>> +       struct pic32_reg_atomic cnpu;
>> +       struct pic32_reg_atomic cnpd;
>> +       struct pic32_reg_atomic cncon;
>> +};
>> +
>> +enum {
>> +       MICROCHIP_GPIO_DIR_OUT,
>> +       MICROCHIP_GPIO_DIR_IN,
>> +       MICROCHIP_GPIOS_PER_BANK = 16,
>> +};
>> +
>> +struct pic32_gpio_priv {
>> +       struct pic32_reg_port *regs;
>> +       char name[2];
>> +};
>> +
>> +static int pic32_gpio_get_value(struct udevice *dev, unsigned offset)
>> +{
>> +       struct pic32_gpio_priv *priv = dev_get_priv(dev);
>> +
>> +       return !!(readl(&priv->regs->port.raw) & BIT(offset));
>> +}
>> +
>> +static int pic32_gpio_set_value(struct udevice *dev, unsigned offset,
>> +                               int value)
>> +{
>> +       struct pic32_gpio_priv *priv = dev_get_priv(dev);
>> +       int mask = BIT(offset);
>> +
>> +       if (value)
>> +               writel(mask, &priv->regs->port.set);
>> +       else
>> +               writel(mask, &priv->regs->port.clr);
>> +
>> +       return 0;
>> +}
>> +
>> +static int pic32_gpio_direction(struct udevice *dev, unsigned offset)
>> +{
>> +       struct pic32_gpio_priv *priv = dev_get_priv(dev);
>> +
>> +       if (readl(&priv->regs->ansel.raw) & BIT(offset))
>> +               return -1;
> What does this error mean? Should it be -EPERM? Perhaps add a comment.

It checks whether the pin is still in ANALOG mode. Report error (-EPERM is better) in case of analog. For GPIO to work the pin has to be in DIGITAL mode which is configured in _direction_input(), _direction_output() callbacks.

>> +
>> +       if (readl(&priv->regs->tris.raw) & BIT(offset))
>> +               return MICROCHIP_GPIO_DIR_IN;
>> +       else
>> +               return MICROCHIP_GPIO_DIR_OUT;
>> +}
>> +
>> +static int pic32_gpio_direction_input(struct udevice *dev, unsigned offset)
>> +{
>> +       struct pic32_gpio_priv *priv = dev_get_priv(dev);
>> +       int mask = BIT(offset);
>> +
>> +       writel(mask, &priv->regs->ansel.clr);
>> +       writel(mask, &priv->regs->tris.set);
>> +
>> +       return 0;
>> +}
>> +
>> +static int pic32_gpio_direction_output(struct udevice *dev,
>> +                                      unsigned offset, int value)
>> +{
>> +       struct pic32_gpio_priv *priv = dev_get_priv(dev);
>> +       int mask = BIT(offset);
>> +
>> +       writel(mask, &priv->regs->ansel.clr);
>> +       writel(mask, &priv->regs->tris.clr);
>> +
>> +       pic32_gpio_set_value(dev, offset, value);
>> +       return 0;
>> +}
>> +
>> +static int pic32_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
>> +                           struct fdtdec_phandle_args *args)
>> +{
>> +       desc->offset = args->args[0];
> This is done automatically in gpio_find_and_xlate(), so you shouldn't need it.
>
ack. Will drop.

>> +       desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
>> +
>> +       return 0;
>> +}
>> +
>> +static int pic32_gpio_get_function(struct udevice *dev, unsigned offset)
>> +{
>> +       int ret = GPIOF_UNUSED;
>> +
>> +       switch (pic32_gpio_direction(dev, offset)) {
>> +       case MICROCHIP_GPIO_DIR_OUT:
>> +               ret = GPIOF_OUTPUT;
>> +               break;
>> +       case MICROCHIP_GPIO_DIR_IN:
>> +               ret = GPIOF_INPUT;
>> +               break;
>> +       default:
>> +               ret = GPIOF_UNUSED;
>> +               break;
>> +       }
>> +       return ret;
>> +}
>> +
>> +static const struct dm_gpio_ops gpio_pic32_ops = {
>> +       .direction_input        = pic32_gpio_direction_input,
>> +       .direction_output       = pic32_gpio_direction_output,
>> +       .get_value              = pic32_gpio_get_value,
>> +       .set_value              = pic32_gpio_set_value,
>> +       .get_function           = pic32_gpio_get_function,
>> +       .xlate                  = pic32_gpio_xlate,
>> +};
>> +
>> +static int pic32_gpio_probe(struct udevice *dev)
>> +{
>> +       struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
>> +       struct pic32_gpio_priv *priv = dev_get_priv(dev);
>> +       fdt_addr_t addr;
>> +       fdt_size_t size;
>> +       char *end;
>> +       int bank;
>> +
>> +       addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg", &size);
>> +       if (addr == FDT_ADDR_T_NONE)
>> +               return -EINVAL;
>> +
>> +       priv->regs = ioremap(addr, size);
>> +       if (!priv->regs)
>> +               return -EINVAL;
>> +
>> +       uc_priv->gpio_count = MICROCHIP_GPIOS_PER_BANK;
>> +       end = strrchr(dev->name, '@');
>> +       bank = trailing_strtoln(dev->name, end);
>> +       priv->name[0] = 'A' + bank;
>> +       uc_priv->bank_name = priv->name;
>> +
>> +       return 0;
>> +}
>> +
>> +static const struct udevice_id pic32_gpio_ids[] = {
>> +       { .compatible = "microchip,pic32mzda-gpio" },
>> +       { }
>> +};
>> +
>> +U_BOOT_DRIVER(gpio_pic32) = {
>> +       .name           = "gpio_pic32",
>> +       .id             = UCLASS_GPIO,
>> +       .of_match       = pic32_gpio_ids,
>> +       .ops            = &gpio_pic32_ops,
>> +       .probe          = pic32_gpio_probe,
>> +       .priv_auto_alloc_size   = sizeof(struct pic32_gpio_priv),
>> +};
>> --
>> 1.8.3.1
>>
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 13/14] drivers: net: Add ethernet driver for Microchip PIC32.
  2016-01-13 14:56   ` Tom Rini
@ 2016-01-14 10:29     ` Purna Chandra Mandal
  0 siblings, 0 replies; 62+ messages in thread
From: Purna Chandra Mandal @ 2016-01-14 10:29 UTC (permalink / raw)
  To: u-boot

On 01/13/2016 08:26 PM, Tom Rini wrote:

> On Tue, Jan 12, 2016 at 03:48:28PM +0530, Purna Chandra Mandal wrote:
>
>> This driver implements MAC and MII layer of the ethernet controller.
>> Network data transfer is handled by controller internal DMA engine.
>> Ethernet controller is configurable through device-tree file.
>>
>> Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> [snip]
>> +/* cache operation helper */
>> +#define __dcache_flush(__a, __l) \
>> +	flush_dcache_range((ulong)(__a),  ((__l) + (ulong)(__a)))
>> +
>> +#define __dcache_invalidate(__a, __l) \
>> +	invalidate_dcache_range((ulong)(__a),  ((__l) + (ulong)(__a)))
> Why using these helper functions instead of directly?  Yes, we may be
> casting in some cases and if that's how it must be, so be it (it's how
> we're doing it in other drivers).  Thanks!

Thanks, Will drop these helpers/macros.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 03/14] drivers: clk: Add clock driver for Microchip PIC32 Microcontroller.
  2016-01-14  6:04     ` Purna Chandra Mandal
@ 2016-01-14 12:30       ` Tom Rini
  0 siblings, 0 replies; 62+ messages in thread
From: Tom Rini @ 2016-01-14 12:30 UTC (permalink / raw)
  To: u-boot

On Thu, Jan 14, 2016 at 11:34:27AM +0530, Purna Chandra Mandal wrote:
> On 01/13/2016 08:25 PM, Tom Rini wrote:
> 
> > On Tue, Jan 12, 2016 at 03:48:18PM +0530, Purna Chandra Mandal wrote:
> >
> >> PIC32 clock module consists of multiple oscillators, PLLs, mutiplexers
> >> and dividers capable of supplying clock to various controllers
> >> on or off-chip.
> > [snip]
> >>  include/dt-bindings/clock/microchip,clock.h        |  29 ++
> > Has this been submitted for the kernel and reviewed there as well
> > already?  Thanks!
> >
> Clock driver in kernel is under review.
> [1] clock driver: https://lkml.org/lkml/2016/1/7/764
> [0] clock binding: https://lkml.org/lkml/2016/1/7/762
>  
> Please note clock driver in Linux kernel is implemented in more elaborate/descriptive way - all the sub-modules are individually defined in device-tree (having "#clock-cells = <0>") and their phandles are directly
> referred in clock clients so there was no need of having dt-binding header.

Note that we really must have the same DT functional in both cases.  So
it's fine to have extra nodes that U-Boot doesn't use.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160114/17e550aa/attachment.sig>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 13/14] drivers: net: Add ethernet driver for Microchip PIC32.
  2016-01-14 10:05     ` Purna Chandra Mandal
@ 2016-01-14 14:01       ` Daniel Schwierzeck
  0 siblings, 0 replies; 62+ messages in thread
From: Daniel Schwierzeck @ 2016-01-14 14:01 UTC (permalink / raw)
  To: u-boot

Am Donnerstag, den 14.01.2016, 15:35 +0530 schrieb Purna Chandra
Mandal:
> On 01/13/2016 09:07 PM, Daniel Schwierzeck wrote:
> 
> > Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra
> > Mandal:
> > > This driver implements MAC and MII layer of the ethernet
> > > controller.
> > > Network data transfer is handled by controller internal DMA
> > > engine.
> > > Ethernet controller is configurable through device-tree file.
> > > 
> > > Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> > > 
> > > 
> > > ---
> > > 
> > > Changes in v3:
> > > - merge wrappers with eth operation callbacks
> > > - read phy address from device-tree
> > > - rename functions (e.g. _eth_xyz() with pic32_eth_xyz())
> > > 
> > > Changes in v2: None
> > > 
> > >  drivers/net/Kconfig      |   7 +
> > >  drivers/net/Makefile     |   1 +
> > >  drivers/net/pic32_eth.c  | 606
> > > +++++++++++++++++++++++++++++++++++++++++++++++
> > >  drivers/net/pic32_eth.h  | 171 +++++++++++++
> > >  drivers/net/pic32_mdio.c | 121 ++++++++++
> > >  5 files changed, 906 insertions(+)
> > >  create mode 100644 drivers/net/pic32_eth.c
> > >  create mode 100644 drivers/net/pic32_eth.h
> > >  create mode 100644 drivers/net/pic32_mdio.c
> > > 
> > > diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> > > index ae5e78d..dc49493 100644
> > > --- a/drivers/net/Kconfig
> > > +++ b/drivers/net/Kconfig
> > > @@ -108,4 +108,11 @@ config ZYNQ_GEM
> > >  	help
> > >  	  This MAC is present in Xilinx Zynq and ZynqMP SoCs.
> > >  
> > > +config PIC32_ETH
> > > +	bool "Microchip PIC32 Ethernet Support"
> > > +	depends on MACH_PIC32
> > should be
> > 
> > depends on DM_ETH && MACH_PIC32
> > select PHYLIB
> 
> ack.
> 
> > > +	help
> > > +	  This driver implements 10/100 Mbps Ethernet and MAC
> > > layer
> > > for
> > > +	  Microchip PIC32 microcontrollers.
> > > +
> > >  endif # NETDEVICES
> > > diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> > > index 150470c..33a81ee 100644
> > > --- a/drivers/net/Makefile
> > > +++ b/drivers/net/Makefile
> > > @@ -72,3 +72,4 @@ obj-$(CONFIG_FSL_MC_ENET) += fsl-mc/
> > >  obj-$(CONFIG_FSL_MC_ENET) += ldpaa_eth/
> > >  obj-$(CONFIG_FSL_MEMAC) += fm/memac_phy.o
> > >  obj-$(CONFIG_VSC9953) += vsc9953.o
> > > +obj-$(CONFIG_PIC32_ETH) += pic32_mdio.o pic32_eth.o
> > > diff --git a/drivers/net/pic32_eth.c b/drivers/net/pic32_eth.c
> > > new file mode 100644
> > > index 0000000..1cef62e
> > > --- /dev/null
> > > +++ b/drivers/net/pic32_eth.c
> > > @@ -0,0 +1,606 @@
> > > +/*
> > > + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
> > > + *
> > > + * SPDX-License-Identifier:	GPL-2.0+
> > > + *
> > > + */
> > > +#include <common.h>
> > > +#include <errno.h>
> > > +#include <dm.h>
> > > +#include <net.h>
> > > +#include <miiphy.h>
> > > +#include <console.h>
> > > +#include <wait_bit.h>
> > > +#include <asm/gpio.h>
> > > +
> > > +#include "pic32_eth.h"
> > > +
> > > +#define MAX_RX_BUF_SIZE		1536
> > > +#define MAX_RX_DESCR		PKTBUFSRX
> > > +#define MAX_TX_DESCR		2
> > > +
> > > +DECLARE_GLOBAL_DATA_PTR;
> > > +
> > > +struct pic32eth_dev {
> > > +	struct eth_dma_desc rxd_ring[MAX_RX_DESCR];
> > > +	struct eth_dma_desc txd_ring[MAX_TX_DESCR];
> > > +	u32 rxd_idx; /* index of RX desc to read */
> > > +	/* regs */
> > > +	struct pic32_ectl_regs *ectl_regs;
> > > +	struct pic32_emac_regs *emac_regs;
> > > +	/* Phy */
> > > +	struct phy_device *phydev;
> > > +	phy_interface_t phyif;
> > > +	u32 phy_addr;
> > > +	struct gpio_desc rst_gpio;
> > > +};
> > > +
> > > +void __weak board_netphy_reset(void *dev)
> > > +{
> > > +	struct pic32eth_dev *priv = (struct pic32eth_dev *)dev;
> > the cast is not necessary
> 
> ack. Will remove,
> 
> > > +
> > > +	if (!dm_gpio_is_valid(&priv->rst_gpio))
> > > +		return;
> > > +
> > > +	/* phy reset */
> > > +	dm_gpio_set_value(&priv->rst_gpio, 0);
> > > +	udelay(300);
> > > +	dm_gpio_set_value(&priv->rst_gpio, 1);
> > > +	udelay(300);
> > > +}
> > > +
> > > +/* Initialize mii(MDIO) interface, discover which PHY is
> > > + * attached to the device, and configure it properly.
> > > + */
> > > +static int pic32_mii_init(struct pic32eth_dev *priv)
> > > +{
> > > +	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
> > > +	struct pic32_emac_regs *emac_p = priv->emac_regs;
> > > +
> > > +	/* board phy reset */
> > > +	board_netphy_reset(priv);
> > > +
> > > +	/* disable RX, TX & all transactions */
> > > +	writel(ETHCON_ON | ETHCON_TXRTS | ETHCON_RXEN, &ectl_p
> > > ->con1.clr);
> > > +
> > > +	/* wait till busy */
> > > +	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY,
> > > false,
> > > +		     CONFIG_SYS_HZ, false);
> > > +
> > > +	/* turn controller ON to access PHY over MII */
> > > +	writel(ETHCON_ON, &ectl_p->con1.set);
> > > +
> > > +	mdelay(10);
> > > +
> > > +	/* reset MAC */
> > > +	writel(EMAC_SOFTRESET, &emac_p->cfg1.set); /* reset
> > > assert
> > > */
> > > +	mdelay(10);
> > > +	writel(EMAC_SOFTRESET, &emac_p->cfg1.clr); /* reset
> > > deassert
> > > */
> > > +
> > > +	/* initialize MDIO/MII */
> > > +	if (priv->phyif == PHY_INTERFACE_MODE_RMII) {
> > > +		writel(EMAC_RMII_RESET, &emac_p->supp.set);
> > > +		mdelay(10);
> > > +		writel(EMAC_RMII_RESET, &emac_p->supp.clr);
> > > +	}
> > > +
> > > +	return pic32_mdio_init(PIC32_MDIO_NAME, (ulong)&emac_p
> > > ->mii);
> > > +}
> > > +
> > > +static int pic32_phy_init(struct pic32eth_dev *priv, struct
> > > udevice
> > > *dev)
> > > +{
> > > +	struct mii_dev *mii;
> > > +
> > > +	mii = miiphy_get_dev_by_name(PIC32_MDIO_NAME);
> > > +
> > > +	/* find & connect PHY */
> > > +	priv->phydev = phy_connect(mii, priv->phy_addr,
> > > +				   dev, priv->phyif);
> > > +	if (!priv->phydev) {
> > > +		printf("%s: %s: Error, PHY connect\n", __FILE__,
> > > __func__);
> > > +		return 0;
> > > +	}
> > > +
> > > +	/* Wait for phy to complete reset */
> > > +	mdelay(10);
> > > +
> > > +	/* configure supported modes */
> > > +	priv->phydev->supported = SUPPORTED_10baseT_Half |
> > > +				  SUPPORTED_10baseT_Full |
> > > +				  SUPPORTED_100baseT_Half |
> > > +				  SUPPORTED_100baseT_Full |
> > > +				  SUPPORTED_Autoneg;
> > > +
> > > +	priv->phydev->advertising = ADVERTISED_10baseT_Half |
> > > +				    ADVERTISED_10baseT_Full |
> > > +				    ADVERTISED_100baseT_Half |
> > > +				    ADVERTISED_100baseT_Full |
> > > +				    ADVERTISED_Autoneg;
> > > +
> > > +	priv->phydev->autoneg = AUTONEG_ENABLE;
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +/* Configure MAC based on negotiated speed and duplex
> > > + * reported by PHY.
> > > + */
> > > +static int pic32_mac_adjust_link(struct pic32eth_dev *priv)
> > > +{
> > > +	struct phy_device *phydev = priv->phydev;
> > > +	struct pic32_emac_regs *emac_p = priv->emac_regs;
> > > +
> > > +	if (!phydev->link) {
> > > +		printf("%s: No link.\n", phydev->dev->name);
> > > +		return -EINVAL;
> > > +	}
> > > +
> > > +	if (phydev->duplex) {
> > > +		writel(EMAC_FULLDUP, &emac_p->cfg2.set);
> > > +		writel(FULLDUP_GAP_TIME, &emac_p->ipgt.raw);
> > > +	} else {
> > > +		writel(EMAC_FULLDUP, &emac_p->cfg2.clr);
> > > +		writel(HALFDUP_GAP_TIME, &emac_p->ipgt.raw);
> > > +	}
> > > +
> > > +	switch (phydev->speed) {
> > > +	case SPEED_100:
> > > +		writel(EMAC_RMII_SPD100, &emac_p->supp.set);
> > > +		break;
> > > +	case SPEED_10:
> > > +		writel(EMAC_RMII_SPD100, &emac_p->supp.clr);
> > > +		break;
> > > +	default:
> > > +		printf("%s: Speed was bad\n", phydev->dev
> > > ->name);
> > > +		return -EINVAL;
> > > +	}
> > > +
> > > +	printf("pic32eth: PHY is %s with %dbase%s, %s\n",
> > > +	       phydev->drv->name, phydev->speed,
> > > +	       (phydev->port == PORT_TP) ? "T" : "X",
> > > +	       (phydev->duplex) ? "full" : "half");
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static void pic32_mac_init(struct pic32eth_dev *priv, u8
> > > *macaddr)
> > > +{
> > > +	struct pic32_emac_regs *emac_p = priv->emac_regs;
> > > +	u32 stat = 0, v;
> > > +	u64 expire;
> > > +
> > > +	v = EMAC_TXPAUSE | EMAC_RXPAUSE | EMAC_RXENABLE;
> > > +	writel(v, &emac_p->cfg1.raw);
> > > +
> > > +	v = EMAC_EXCESS | EMAC_AUTOPAD | EMAC_PADENABLE |
> > > +	    EMAC_CRCENABLE | EMAC_LENGTHCK | EMAC_FULLDUP;
> > > +	writel(v, &emac_p->cfg2.raw);
> > > +
> > > +	/* recommended back-to-back inter-packet gap for 10 Mbps
> > > half duplex */
> > > +	writel(HALFDUP_GAP_TIME, &emac_p->ipgt.raw);
> > > +
> > > +	/* recommended non-back-to-back interpacket gap is 0xc12
> > > */
> > > +	writel(0xc12, &emac_p->ipgr.raw);
> > > +
> > > +	/* recommended collision window retry limit is 0x370F */
> > > +	writel(0x370f, &emac_p->clrt.raw);
> > > +
> > > +	/* set maximum frame length: allow VLAN tagged frame */
> > > +	writel(0x600, &emac_p->maxf.raw);
> > > +
> > > +	/* set the mac address */
> > > +	writel(macaddr[0] | (macaddr[1] << 8), &emac_p
> > > ->sa2.raw);
> > > +	writel(macaddr[2] | (macaddr[3] << 8), &emac_p
> > > ->sa1.raw);
> > > +	writel(macaddr[4] | (macaddr[5] << 8), &emac_p
> > > ->sa0.raw);
> > > +
> > > +	/* default, enable 10 Mbps operation */
> > > +	writel(EMAC_RMII_SPD100, &emac_p->supp.clr);
> > > +
> > > +	/* wait until link status UP or deadline elapsed */
> > > +	expire = get_ticks() + get_tbclk() * 2;
> > > +	for (; get_ticks() < expire;) {
> > > +		stat = phy_read(priv->phydev, priv->phy_addr,
> > > MII_BMSR);
> > > +		if (stat & BMSR_LSTATUS)
> > > +			break;
> > > +	}
> > > +
> > > +	if (!(stat & BMSR_LSTATUS))
> > > +		printf("MAC: Link is DOWN!\n");
> > > +
> > > +	/* delay to stabilize before any tx/rx */
> > > +	mdelay(10);
> > > +}
> > > +
> > > +static void pic32_mac_reset(struct pic32eth_dev *priv)
> > > +{
> > > +	struct pic32_emac_regs *emac_p = priv->emac_regs;
> > > +	struct mii_dev *mii;
> > > +
> > > +	/* Reset MAC */
> > > +	writel(EMAC_SOFTRESET, &emac_p->cfg1.raw);
> > > +	mdelay(10);
> > > +
> > > +	/* clear reset */
> > > +	writel(0, &emac_p->cfg1.raw);
> > > +
> > > +	/* Reset MII */
> > > +	mii = priv->phydev->bus;
> > > +	if (mii && mii->reset)
> > > +		mii->reset(mii);
> > > +}
> > > +
> > > +/* initializes the MAC and PHY, then establishes a link */
> > > +static void pic32_ctrl_reset(struct pic32eth_dev *priv)
> > > +{
> > > +	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
> > > +	u32 v;
> > > +
> > > +	/* disable RX, TX & any other transactions */
> > > +	writel(ETHCON_ON | ETHCON_TXRTS | ETHCON_RXEN, &ectl_p
> > > ->con1.clr);
> > > +
> > > +	/* wait till busy */
> > > +	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY,
> > > false,
> > > +		     CONFIG_SYS_HZ, false);
> > > +	/* decrement received buffcnt to zero. */
> > > +	while (readl(&ectl_p->stat.raw) & ETHSTAT_BUFCNT)
> > > +		writel(ETHCON_BUFCDEC, &ectl_p->con1.set);
> > > +
> > > +	/* clear any existing interrupt event */
> > > +	writel(0xffffffff, &ectl_p->irq.clr);
> > > +
> > > +	/* clear RX/TX start address */
> > > +	writel(0xffffffff, &ectl_p->txst.clr);
> > > +	writel(0xffffffff, &ectl_p->rxst.clr);
> > > +
> > > +	/* clear the receive filters */
> > > +	writel(0x00ff, &ectl_p->rxfc.clr);
> > > +
> > > +	/* set the receive filters
> > > +	 * ETH_FILT_CRC_ERR_REJECT
> > > +	 * ETH_FILT_RUNT_REJECT
> > > +	 * ETH_FILT_UCAST_ACCEPT
> > > +	 * ETH_FILT_MCAST_ACCEPT
> > > +	 * ETH_FILT_BCAST_ACCEPT
> > > +	 */
> > > +	v = ETHRXFC_BCEN | ETHRXFC_MCEN | ETHRXFC_UCEN |
> > > +	    ETHRXFC_RUNTEN | ETHRXFC_CRCOKEN;
> > > +	writel(v, &ectl_p->rxfc.set);
> > > +
> > > +	/* turn controller ON to access PHY over MII */
> > > +	writel(ETHCON_ON, &ectl_p->con1.set);
> > > +}
> > > +
> > > +static void pic32_rx_desc_init(struct pic32eth_dev *priv)
> > > +{
> > > +	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
> > > +	struct eth_dma_desc *rxd;
> > > +	u32 idx, bufsz;
> > > +
> > > +	priv->rxd_idx = 0;
> > > +	for (idx = 0; idx < MAX_RX_DESCR; idx++) {
> > > +		rxd = &priv->rxd_ring[idx];
> > > +
> > > +		/* hw owned */
> > > +		rxd->hdr = EDH_NPV | EDH_EOWN | EDH_STICKY;
> > > +
> > > +		/* packet buffer address */
> > > +		rxd->data_buff =
> > > virt_to_phys(net_rx_packets[idx]);
> > > +
> > > +		/* link to next desc */
> > > +		rxd->next_ed = virt_to_phys(rxd + 1);
> > > +
> > > +		/* reset status */
> > > +		rxd->stat1 = 0;
> > > +		rxd->stat2 = 0;
> > > +
> > > +		/* decrement bufcnt */
> > > +		writel(ETHCON_BUFCDEC, &ectl_p->con1.set);
> > > +	}
> > > +
> > > +	/* link last descr to beginning of list */
> > > +	rxd->next_ed = virt_to_phys(&priv->rxd_ring[0]);
> > > +
> > > +	/* flush rx ring */
> > > +	__dcache_flush(priv->rxd_ring, sizeof(priv->rxd_ring));
> > > +
> > > +	/* set rx desc-ring start address */
> > > +	writel((ulong)virt_to_phys(&priv->rxd_ring[0]), &ectl_p
> > > ->rxst.raw);
> > > +
> > > +	/* RX Buffer size */
> > > +	bufsz = readl(&ectl_p->con2.raw);
> > > +	bufsz &= ~(ETHCON_RXBUFSZ << ETHCON_RXBUFSZ_SHFT);
> > > +	bufsz |= ((MAX_RX_BUF_SIZE / 16) <<
> > > ETHCON_RXBUFSZ_SHFT);
> > > +	writel(bufsz, &ectl_p->con2.raw);
> > > +
> > > +	/* enable the receiver in hardware which allows hardware
> > > +	 * to DMA received pkts to the descriptor pointer
> > > address.
> > > +	 */
> > > +	writel(ETHCON_RXEN, &ectl_p->con1.set);
> > > +}
> > > +
> > > +static int pic32_eth_start(struct udevice *dev)
> > > +{
> > > +	struct eth_pdata *pdata = dev_get_platdata(dev);
> > > +	struct pic32eth_dev *priv = dev_get_priv(dev);
> > > +
> > > +	/* controller */
> > > +	pic32_ctrl_reset(priv);
> > > +
> > > +	/* reset MAC */
> > > +	pic32_mac_reset(priv);
> > > +
> > > +	/* configure PHY */
> > > +	phy_config(priv->phydev);
> > > +
> > > +	/* initialize MAC */
> > > +	pic32_mac_init(priv, &pdata->enetaddr[0]);
> > > +
> > > +	/* init RX descriptor; TX descriptors are handled in
> > > xmit */
> > > +	pic32_rx_desc_init(priv);
> > > +
> > > +	/* Start up & update link status of PHY */
> > > +	phy_startup(priv->phydev);
> > > +
> > > +	/* adjust mac with phy link status */
> > > +	return pic32_mac_adjust_link(priv);
> > > +}
> > > +
> > > +static void pic32_eth_stop(struct udevice *dev)
> > > +{
> > > +	struct pic32eth_dev *priv = dev_get_priv(dev);
> > > +	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
> > > +	struct pic32_emac_regs *emac_p = priv->emac_regs;
> > > +
> > > +	/* Reset the phy if the controller is enabled */
> > > +	if (readl(&ectl_p->con1.raw) & ETHCON_ON)
> > > +		phy_reset(priv->phydev);
> > > +
> > > +	/* Shut down the PHY */
> > > +	phy_shutdown(priv->phydev);
> > > +
> > > +	/* Stop rx/tx */
> > > +	writel(ETHCON_TXRTS | ETHCON_RXEN, &ectl_p->con1.clr);
> > > +	mdelay(10);
> > > +
> > > +	/* reset MAC */
> > > +	writel(EMAC_SOFTRESET, &emac_p->cfg1.raw);
> > > +
> > > +	/* clear reset */
> > > +	writel(0, &emac_p->cfg1.raw);
> > > +	mdelay(10);
> > > +
> > > +	/* disable controller */
> > > +	writel(ETHCON_ON, &ectl_p->con1.clr);
> > > +	mdelay(10);
> > > +
> > > +	/* wait until everything is down */
> > > +	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY,
> > > false,
> > > +		     2 * CONFIG_SYS_HZ, false);
> > > +
> > > +	/* clear any existing interrupt event */
> > > +	writel(0xffffffff, &ectl_p->irq.clr);
> > > +}
> > > +
> > > +static int pic32_eth_send(struct udevice *dev, void *packet, int
> > > length)
> > > +{
> > > +	struct pic32eth_dev *priv = dev_get_priv(dev);
> > > +	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
> > > +	struct eth_dma_desc *txd;
> > > +	u64 deadline;
> > > +
> > > +	txd = &priv->txd_ring[0];
> > > +
> > > +	/* set proper flags & length in descriptor header */
> > > +	txd->hdr = EDH_SOP | EDH_EOP | EDH_EOWN |
> > > EDH_BCOUNT(length);
> > > +
> > > +	/* pass buffer address to hardware */
> > > +	txd->data_buff = virt_to_phys(packet);
> > > +
> > > +	debug("%s: %d / .hdr %x, .data_buff %x, .stat %x,
> > > .nexted
> > > %x\n",
> > > +	      __func__, __LINE__, txd->hdr, txd->data_buff, txd
> > > ->stat2,
> > > +	      txd->next_ed);
> > > +
> > > +	/* cache flush (packet) */
> > > +	__dcache_flush(packet, length);
> > > +
> > > +	/* cache flush (txd) */
> > > +	__dcache_flush(txd, sizeof(*txd));
> > > +
> > > +	/* pass descriptor table base to h/w */
> > > +	writel(virt_to_phys(txd), &ectl_p->txst.raw);
> > > +
> > > +	/* ready to send enabled, hardware can now send the
> > > packet(s) */
> > > +	writel(ETHCON_TXRTS | ETHCON_ON, &ectl_p->con1.set);
> > > +
> > > +	/* wait until tx has completed and h/w has released
> > > ownership
> > > +	 * of the tx descriptor or timeout elapsed.
> > > +	 */
> > > +	deadline = get_ticks() + get_tbclk();
> > > +	for (;;) {
> > > +		/* check timeout */
> > > +		if (get_ticks() > deadline)
> > > +			return -ETIMEDOUT;
> > > +
> > > +		if (ctrlc())
> > > +			return -EINTR;
> > > +
> > > +		/* tx completed ? */
> > > +		if (readl(&ectl_p->con1.raw) & ETHCON_TXRTS) {
> > > +			udelay(1);
> > > +			continue;
> > > +		}
> > > +
> > > +		/* h/w not released ownership yet? */
> > > +		__dcache_invalidate(txd, sizeof(*txd));
> > > +		if (!(txd->hdr & EDH_EOWN))
> > > +			break;
> > > +	}
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static int pic32_eth_recv(struct udevice *dev, int flags, uchar
> > > **packetp)
> > > +{
> > > +	struct pic32eth_dev *priv = dev_get_priv(dev);
> > > +	struct eth_dma_desc *rxd;
> > > +	u32 idx = priv->rxd_idx;
> > > +	u32 rx_count;
> > > +
> > > +	/* find the next ready to receive */
> > > +	rxd = &priv->rxd_ring[idx];
> > > +
> > > +	__dcache_invalidate(rxd, sizeof(*rxd));
> > > +	/* check if owned by MAC */
> > > +	if (rxd->hdr & EDH_EOWN)
> > > +		return -EAGAIN;
> > > +
> > > +	/* Sanity check on header: SOP and EOP  */
> > > +	if ((rxd->hdr & (EDH_SOP | EDH_EOP)) != (EDH_SOP |
> > > EDH_EOP))
> > > {
> > > +		printf("%s: %s, rx pkt across multiple descr\n",
> > > +		       __FILE__, __func__);
> > > +		return 0;
> > > +	}
> > > +
> > > +	debug("%s: %d /idx %i, hdr=%x, data_buff %x, stat %x,
> > > nexted
> > > %x\n",
> > > +	      __func__, __LINE__, idx, rxd->hdr,
> > > +	      rxd->data_buff, rxd->stat2, rxd->next_ed);
> > > +
> > > +	/* Sanity check on rx_stat: OK, CRC */
> > > +	if (!RSV_RX_OK(rxd->stat2) || RSV_CRC_ERR(rxd->stat2)) {
> > > +		debug("%s: %s: Error, rx problem detected\n",
> > > +		      __FILE__, __func__);
> > > +		return 0;
> > > +	}
> > > +
> > > +	/* invalidate dcache */
> > > +	rx_count = RSV_RX_COUNT(rxd->stat2);
> > > +	__dcache_invalidate(net_rx_packets[idx], rx_count);
> > > +
> > > +	/* Pass the packet to protocol layer */
> > > +	*packetp = net_rx_packets[idx];
> > > +
> > > +	/* increment number of bytes rcvd (ignore CRC) */
> > > +	return rx_count - 4;
> > > +}
> > > +
> > > +static int pic32_eth_free_pkt(struct udevice *dev, uchar
> > > *packet,
> > > int length)
> > > +{
> > > +	struct pic32eth_dev *priv = dev_get_priv(dev);
> > > +	struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
> > > +	struct eth_dma_desc *rxd;
> > > +	int idx = priv->rxd_idx;
> > > +
> > > +	/* sanity check */
> > > +	if (packet != net_rx_packets[idx]) {
> > > +		printf("rxd_id %d: packet is not matched,\n",
> > > idx);
> > > +		return -EAGAIN;
> > > +	}
> > > +
> > > +	/* prepare for receive */
> > > +	rxd = &priv->rxd_ring[idx];
> > > +	rxd->hdr = EDH_STICKY | EDH_NPV | EDH_EOWN;
> > > +
> > > +	__dcache_flush(rxd, sizeof(*rxd));
> > > +
> > > +	/* decrement rx pkt count */
> > > +	writel(ETHCON_BUFCDEC, &ectl_p->con1.set);
> > > +
> > > +	debug("%s: %d / idx %i, hdr %x, data_buff %x, stat %x,
> > > nexted %x\n",
> > > +	      __func__, __LINE__, idx, rxd->hdr, rxd->data_buff,
> > > +	      rxd->stat2, rxd->next_ed);
> > > +
> > > +	priv->rxd_idx = (priv->rxd_idx + 1) % MAX_RX_DESCR;
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static const struct eth_ops pic32_eth_ops = {
> > > +	.start		= pic32_eth_start,
> > > +	.send		= pic32_eth_send,
> > > +	.recv		= pic32_eth_recv,
> > > +	.free_pkt	= pic32_eth_free_pkt,
> > > +	.stop		= pic32_eth_stop,
> > > +};
> > > +
> > > +static int pic32_eth_probe(struct udevice *dev)
> > > +{
> > > +	struct eth_pdata *pdata = dev_get_platdata(dev);
> > your driver private data should be stored in struct pic32eth_dev
> 
> Please see below.
> 
> > > +	struct pic32eth_dev *priv = dev_get_priv(dev);
> > > +	const char *phy_mode;
> > > +	void __iomem *iobase;
> > > +	fdt_addr_t addr;
> > > +	fdt_size_t size;
> > > +	int offset = 0;
> > > +	int phy_addr = -1;
> > > +
> > > +	addr = fdtdec_get_addr_size(gd->fdt_blob, dev
> > > ->of_offset,
> > > "reg", &size);
> > > +	if (addr == FDT_ADDR_T_NONE)
> > > +		return -EINVAL;
> > > +
> > > +	iobase = ioremap(addr, size);
> > > +	if (!iobase)
> > > +		return -EINVAL;
> > you can drop this check. ioremap() always returns a mapped address.
> 
> ack.
> 
> > > +
> > > +	pdata->iobase = (phys_addr_t)addr;
> > > +
> > > +	/* get phy mode */
> > > +	pdata->phy_interface = -1;
> > > +	phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset,
> > > "phy
> > > -mode", NULL);
> > > +	if (phy_mode)
> > > +		pdata->phy_interface =
> > > phy_get_interface_by_name(phy_mode);
> > > +	if (pdata->phy_interface == -1) {
> > > +		debug("%s: Invalid PHY interface '%s'\n",
> > > __func__,
> > > phy_mode);
> > > +		return -EINVAL;
> > > +	}
> > your driver private data should be stored in struct pic32eth_dev.
> > Only
> > if a arch/SoC does not support device-tree, platdata have to be
> > initialized with PHY address and PHY interface in the board code.
> > Also
> > form a drivers point of view, platdata is read-only and provides
> > board
> > -specific configuration for the driver.
> 
> Please note here (as you pointed out earlier also) driver private
> data (as defined by struct pic32eth_dev) is maintained at priv field
> of udevice. This is sufficient for the driver to work.
> On the other hand, u-boot network library expects 'struct eth_pdata'
> (as platdata) to be filled by the driver instance with correct
> information (like baseaddr, phy_interface, enetaddr). Network library
> uses this data structure to preprate, process (create-random-if-unset
> or download-from-some-storage-based-on-env or some else) and pass to
> the relevant ethernet device at different time as part of some
> callback. I have taken inspiration from other net drivers
> (drivers/net/).

ok, I've missed that part. I would expect that such data should be
stored in uclass private data. Please ignore my comment.

> 
> > > +
> > > +	/* get phy addr */
> > > +	offset = fdtdec_lookup_phandle(gd->fdt_blob, dev
> > > ->of_offset,
> > > +				       "phy-handle");
> > > +	if (offset > 0)
> > > +		phy_addr = fdtdec_get_int(gd->fdt_blob, offset,
> > > "reg", -1);
> > > +
> > > +	/* phy reset gpio */
> > > +	gpio_request_by_name_nodev(gd->fdt_blob, dev->of_offset,
> > > +				   "reset-gpios", 0,
> > > +				   &priv->rst_gpio,
> > > GPIOD_IS_OUT);
> > > +
> > > +	priv->phyif	= pdata->phy_interface;
> > > +	priv->phy_addr	= phy_addr;
> > > +	priv->ectl_regs	= iobase;
> > > +	priv->emac_regs	= iobase + PIC32_EMAC1CFG1;
> > > +
> > > +	pic32_mii_init(priv);
> > > +
> > > +	return pic32_phy_init(priv, dev);
> > > +}
> > > +
> > > +static int pic32_eth_remove(struct udevice *dev)
> > > +{
> > > +	struct pic32eth_dev *priv = dev_get_priv(dev);
> > > +	struct mii_dev *bus;
> > > +
> > > +	dm_gpio_free(dev, &priv->rst_gpio);
> > > +	phy_shutdown(priv->phydev);
> > > +	free(priv->phydev);
> > > +	bus = miiphy_get_dev_by_name(PIC32_MDIO_NAME);
> > > +	mdio_unregister(bus);
> > > +	mdio_free(bus);
> > > +	iounmap(priv->ectl_regs);
> > > +	return 0;
> > > +}
> > > +
> > > +static const struct udevice_id pic32_eth_ids[] = {
> > > +	{ .compatible = "microchip,pic32mzda-eth" },
> > > +	{ }
> > > +};
> > > +
> > > +U_BOOT_DRIVER(pic32_ethernet) = {
> > > +	.name			= "pic32_ethernet",
> > > +	.id			= UCLASS_ETH,
> > > +	.of_match		= pic32_eth_ids,
> > > +	.probe			= pic32_eth_probe,
> > > +	.remove			= pic32_eth_remove,
> > > +	.ops			= &pic32_eth_ops,
> > > +	.priv_auto_alloc_size	= sizeof(struct
> > > pic32eth_dev),
> > > +	.platdata_auto_alloc_size	= sizeof(struct
> > > eth_pdata),
> > > +};
> > > diff --git a/drivers/net/pic32_eth.h b/drivers/net/pic32_eth.h
> > > new file mode 100644
> > > index 0000000..4dd443b
> > > --- /dev/null
> > > +++ b/drivers/net/pic32_eth.h
> > > @@ -0,0 +1,171 @@
> > > +/*
> > > + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
> > > + *
> > > + * SPDX-License-Identifier:	GPL-2.0+
> > > + *
> > > + */
> > > +
> > > +#ifndef __MICROCHIP_PIC32_ETH_H_
> > > +#define __MICROCHIP_PIC32_ETH_H_
> > > +
> > > +#include <mach/pic32.h>
> > > +
> > > +/* Ethernet */
> > > +struct pic32_ectl_regs {
> > > +	struct pic32_reg_atomic con1; /* 0x00 */
> > > +	struct pic32_reg_atomic con2; /* 0x10 */
> > > +	struct pic32_reg_atomic txst; /* 0x20 */
> > > +	struct pic32_reg_atomic rxst; /* 0x30 */
> > > +	struct pic32_reg_atomic ht0;  /* 0x40 */
> > > +	struct pic32_reg_atomic ht1;  /* 0x50 */
> > > +	struct pic32_reg_atomic pmm0; /* 0x60 */
> > > +	struct pic32_reg_atomic pmm1; /* 0x70 */
> > > +	struct pic32_reg_atomic pmcs; /* 0x80 */
> > > +	struct pic32_reg_atomic pmo;  /* 0x90 */
> > > +	struct pic32_reg_atomic rxfc; /* 0xa0 */
> > > +	struct pic32_reg_atomic rxwm; /* 0xb0 */
> > > +	struct pic32_reg_atomic ien;  /* 0xc0 */
> > > +	struct pic32_reg_atomic irq;  /* 0xd0 */
> > > +	struct pic32_reg_atomic stat; /* 0xe0 */
> > > +};
> > > +
> > > +struct pic32_mii_regs {
> > > +	struct pic32_reg_atomic mcfg; /* 0x280 */
> > > +	struct pic32_reg_atomic mcmd; /* 0x290 */
> > > +	struct pic32_reg_atomic madr; /* 0x2a0 */
> > > +	struct pic32_reg_atomic mwtd; /* 0x2b0 */
> > > +	struct pic32_reg_atomic mrdd; /* 0x2c0 */
> > > +	struct pic32_reg_atomic mind; /* 0x2d0 */
> > > +};
> > > +
> > > +struct pic32_emac_regs {
> > > +	struct pic32_reg_atomic cfg1; /* 0x200*/
> > > +	struct pic32_reg_atomic cfg2; /* 0x210*/
> > > +	struct pic32_reg_atomic ipgt; /* 0x220*/
> > > +	struct pic32_reg_atomic ipgr; /* 0x230*/
> > > +	struct pic32_reg_atomic clrt; /* 0x240*/
> > > +	struct pic32_reg_atomic maxf; /* 0x250*/
> > > +	struct pic32_reg_atomic supp; /* 0x260*/
> > > +	struct pic32_reg_atomic test; /* 0x270*/
> > > +	struct pic32_mii_regs mii;    /* 0x280 - 0x2d0 */
> > > +	struct pic32_reg_atomic res1; /* 0x2e0 */
> > > +	struct pic32_reg_atomic res2; /* 0x2f0 */
> > > +	struct pic32_reg_atomic sa0;  /* 0x300 */
> > > +	struct pic32_reg_atomic sa1;  /* 0x310 */
> > > +	struct pic32_reg_atomic sa2;  /* 0x320 */
> > > +};
> > > +
> > > +/* ETHCON1 Reg field */
> > > +#define ETHCON_BUFCDEC		BIT(0)
> > > +#define ETHCON_RXEN		BIT(8)
> > > +#define ETHCON_TXRTS		BIT(9)
> > > +#define ETHCON_ON		BIT(15)
> > > +
> > > +/* ETHCON2 Reg field */
> > > +#define ETHCON_RXBUFSZ		0x7f
> > > +#define ETHCON_RXBUFSZ_SHFT	0x4
> > > +
> > > +/* ETHSTAT Reg field */
> > > +#define ETHSTAT_BUSY		BIT(7)
> > > +#define ETHSTAT_BUFCNT		0x00ff0000
> > > +
> > > +/* ETHRXFC Register fields */
> > > +#define ETHRXFC_BCEN		BIT(0)
> > > +#define ETHRXFC_MCEN		BIT(1)
> > > +#define ETHRXFC_UCEN		BIT(3)
> > > +#define ETHRXFC_RUNTEN		BIT(4)
> > > +#define ETHRXFC_CRCOKEN		BIT(5)
> > > +
> > > +/* EMAC1CFG1 register offset */
> > > +#define PIC32_EMAC1CFG1		0x0200
> > > +
> > > +/* EMAC1CFG1 register fields */
> > > +#define EMAC_RXENABLE		BIT(0)
> > > +#define EMAC_RXPAUSE		BIT(2)
> > > +#define EMAC_TXPAUSE		BIT(3)
> > > +#define EMAC_SOFTRESET		BIT(15)
> > > +
> > > +/* EMAC1CFG2 register fields */
> > > +#define EMAC_FULLDUP		BIT(0)
> > > +#define EMAC_LENGTHCK		BIT(1)
> > > +#define EMAC_CRCENABLE		BIT(4)
> > > +#define EMAC_PADENABLE		BIT(5)
> > > +#define EMAC_AUTOPAD		BIT(7)
> > > +#define EMAC_EXCESS		BIT(14)
> > > +
> > > +/* EMAC1IPGT register magic */
> > > +#define FULLDUP_GAP_TIME	0x15
> > > +#define HALFDUP_GAP_TIME	0x12
> > > +
> > > +/* EMAC1SUPP register fields */
> > > +#define EMAC_RMII_SPD100	BIT(8)
> > > +#define EMAC_RMII_RESET		BIT(11)
> > > +
> > > +/* MII Management Configuration Register */
> > > +#define MIIMCFG_RSTMGMT		BIT(15)
> > > +#define MIIMCFG_CLKSEL_DIV40	0x0020	/* 100Mhz / 40
> > > */
> > > +
> > > +/* MII Management Command Register */
> > > +#define MIIMCMD_READ		BIT(0)
> > > +#define MIIMCMD_SCAN		BIT(1)
> > > +
> > > +/* MII Management Address Register */
> > > +#define MIIMADD_REGADDR		0x1f
> > > +#define MIIMADD_REGADDR_SHIFT	0
> > > +#define MIIMADD_PHYADDR_SHIFT	8
> > > +
> > > +/* MII Management Indicator Register */
> > > +#define MIIMIND_BUSY		BIT(0)
> > > +#define MIIMIND_NOTVALID	BIT(2)
> > > +#define MIIMIND_LINKFAIL	BIT(3)
> > > +
> > > +/* Packet Descriptor */
> > > +/* Received Packet Status */
> > > +#define _RSV1_PKT_CSUM		0xffff
> > > +#define _RSV2_CRC_ERR		BIT(20)
> > > +#define _RSV2_LEN_ERR		BIT(21)
> > > +#define _RSV2_RX_OK		BIT(23)
> > > +#define _RSV2_RX_COUNT		0xffff
> > > +
> > > +#define RSV_RX_CSUM(__rsv1)	((__rsv1) & _RSV1_PKT_CSUM)
> > > +#define RSV_RX_COUNT(__rsv2)	((__rsv2) & _RSV2_RX_COUNT)
> > > +#define RSV_RX_OK(__rsv2)	((__rsv2) & _RSV2_RX_OK)
> > > +#define RSV_CRC_ERR(__rsv2)	((__rsv2) & _RSV2_CRC_ERR)
> > > +
> > > +/* Ethernet Hardware Descriptor Header bits */
> > > +#define EDH_EOWN		BIT(7)
> > > +#define EDH_NPV			BIT(8)
> > > +#define EDH_STICKY		BIT(9)
> > > +#define _EDH_BCOUNT		0x07ff0000
> > > +#define EDH_EOP			BIT(30)
> > > +#define EDH_SOP			BIT(31)
> > > +#define EDH_BCOUNT_SHIFT	16
> > > +#define EDH_BCOUNT(len)		((len) <<
> > > EDH_BCOUNT_SHIFT)
> > > +
> > > +/* Ethernet Hardware Descriptors
> > > + * ref: PIC32 Family Reference Manual Table 35-7
> > > + * This structure represents the layout of the DMA
> > > + * memory shared between the CPU and the Ethernet
> > > + * controller.
> > > + */
> > > +/* TX/RX DMA descriptor */
> > > +struct eth_dma_desc {
> > > +	u32 hdr;	/* header */
> > > +	u32 data_buff;	/* data buffer address */
> > > +	u32 stat1;	/* transmit/receive packet status */
> > > +	u32 stat2;	/* transmit/receive packet status */
> > > +	u32 next_ed;	/* next descriptor */
> > > +};
> > > +
> > > +/* cache operation helper */
> > > +#define __dcache_flush(__a, __l) \
> > > +	flush_dcache_range((ulong)(__a),  ((__l) +
> > > (ulong)(__a)))
> > > +
> > > +#define __dcache_invalidate(__a, __l) \
> > > +	invalidate_dcache_range((ulong)(__a),  ((__l) +
> > > (ulong)(__a)))
> > > +
> > > +#define PIC32_MDIO_NAME "PIC32_EMAC"
> > > +
> > > +int pic32_mdio_init(const char *name, ulong ioaddr);
> > > +
> > > +#endif /* __MICROCHIP_PIC32_ETH_H_*/
> > > diff --git a/drivers/net/pic32_mdio.c b/drivers/net/pic32_mdio.c
> > > new file mode 100644
> > > index 0000000..578fc96
> > > --- /dev/null
> > > +++ b/drivers/net/pic32_mdio.c
> > > @@ -0,0 +1,121 @@
> > > +/*
> > > + * pic32_mdio.c: PIC32 MDIO/MII driver, part of pic32_eth.c.
> > > + *
> > > + * Copyright 2015 Microchip Inc.
> > > + *	Purna Chandra Mandal <purna.mandal@microchip.com>
> > > + *
> > > + * SPDX-License-Identifier:	GPL-2.0+
> > > + */
> > > +#include <common.h>
> > > +#include <phy.h>
> > > +#include <miiphy.h>
> > > +#include <errno.h>
> > > +#include <wait_bit.h>
> > > +#include <asm/io.h>
> > > +#include "pic32_eth.h"
> > > +
> > > +static int pic32_mdio_write(struct mii_dev *bus,
> > > +			    int addr, int dev_addr,
> > > +			    int reg, u16 value)
> > > +{
> > > +	u32 v;
> > > +	struct pic32_mii_regs *mii_regs = bus->priv;
> > > +
> > > +	/* Wait for the previous operation to finish */
> > > +	wait_for_bit(__func__, &mii_regs->mind.raw,
> > > MIIMIND_BUSY,
> > > +		     false, CONFIG_SYS_HZ, true);
> > > +
> > > +	/* Put phyaddr and regaddr into MIIMADD */
> > > +	v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg &
> > > MIIMADD_REGADDR);
> > > +	writel(v, &mii_regs->madr.raw);
> > > +
> > > +	/* Initiate a write command */
> > > +	writel(value, &mii_regs->mwtd.raw);
> > > +
> > > +	/* Wait 30 clock cycles for busy flag to be set */
> > > +	udelay(12);
> > > +
> > > +	/* Wait for write to complete */
> > > +	wait_for_bit(__func__, &mii_regs->mind.raw,
> > > MIIMIND_BUSY,
> > > +		     false, CONFIG_SYS_HZ, true);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static int pic32_mdio_read(struct mii_dev *bus, int addr, int
> > > devaddr, int reg)
> > > +{
> > > +	u32 v;
> > > +	struct pic32_mii_regs *mii_regs = bus->priv;
> > > +
> > > +	/* Wait for the previous operation to finish */
> > > +	wait_for_bit(__func__, &mii_regs->mind.raw,
> > > MIIMIND_BUSY,
> > > +		     false, CONFIG_SYS_HZ, true);
> > > +
> > > +	/* Put phyaddr and regaddr into MIIMADD */
> > > +	v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg &
> > > MIIMADD_REGADDR);
> > > +	writel(v, &mii_regs->madr.raw);
> > > +
> > > +	/* Initiate a read command */
> > > +	writel(MIIMCMD_READ, &mii_regs->mcmd.raw);
> > > +
> > > +	/* Wait 30 clock cycles for busy flag to be set */
> > > +	udelay(12);
> > > +
> > > +	/* Wait for read to complete */
> > > +	wait_for_bit(__func__, &mii_regs->mind.raw,
> > > +		     MIIMIND_NOTVALID | MIIMIND_BUSY,
> > > +		     false, CONFIG_SYS_HZ, false);
> > > +
> > > +	/* Clear the command register */
> > > +	writel(0, &mii_regs->mcmd.raw);
> > > +
> > > +	/* Grab the value read from the PHY */
> > > +	v = readl(&mii_regs->mrdd.raw);
> > > +	return v;
> > > +}
> > > +
> > > +static int pic32_mdio_reset(struct mii_dev *bus)
> > > +{
> > > +	struct pic32_mii_regs *mii_regs = bus->priv;
> > > +
> > > +	/* Reset MII (due to new addresses) */
> > > +	writel(MIIMCFG_RSTMGMT, &mii_regs->mcfg.raw);
> > > +
> > > +	/* Wait for the operation to finish */
> > > +	wait_for_bit(__func__, &mii_regs->mind.raw,
> > > MIIMIND_BUSY,
> > > +		     false, CONFIG_SYS_HZ, true);
> > > +
> > > +	/* Clear reset bit */
> > > +	writel(0, &mii_regs->mcfg);
> > > +
> > > +	/* Wait for the operation to finish */
> > > +	wait_for_bit(__func__, &mii_regs->mind.raw,
> > > MIIMIND_BUSY,
> > > +		     false, CONFIG_SYS_HZ, true);
> > > +
> > > +	/* Set the MII Management Clock (MDC) - no faster than
> > > 2.5
> > > MHz */
> > > +	writel(MIIMCFG_CLKSEL_DIV40, &mii_regs->mcfg.raw);
> > > +
> > > +	/* Wait for the operation to finish */
> > > +	wait_for_bit(__func__, &mii_regs->mind.raw,
> > > MIIMIND_BUSY,
> > > +		     false, CONFIG_SYS_HZ, true);
> > > +	return 0;
> > > +}
> > > +
> > > +int pic32_mdio_init(const char *name, ulong ioaddr)
> > > +{
> > > +	struct mii_dev *bus;
> > > +
> > > +	bus = mdio_alloc();
> > > +	if (!bus) {
> > > +		printf("Failed to allocate PIC32-MDIO bus\n");
> > > +		return -ENOMEM;
> > > +	}
> > > +
> > > +	bus->read = pic32_mdio_read;
> > > +	bus->write = pic32_mdio_write;
> > > +	bus->reset = pic32_mdio_reset;
> > > +	strncpy(bus->name, name, sizeof(bus->name));
> > > +	bus->priv = (void *)ioaddr;
> > > +
> > > +	return mdio_register(bus);
> > > +}
> 
-- 
- Daniel

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [U-Boot] [PATCH v3 01/14] MIPS: initialize board_init_f() argument to zero.
  2016-01-14  5:29     ` Purna Chandra Mandal
@ 2016-01-21 14:06       ` Daniel Schwierzeck
  0 siblings, 0 replies; 62+ messages in thread
From: Daniel Schwierzeck @ 2016-01-21 14:06 UTC (permalink / raw)
  To: u-boot

Hi Purna,

Am Donnerstag, den 14.01.2016, 10:59 +0530 schrieb Purna Chandra
Mandal:
> On 01/12/2016 05:59 PM, Daniel Schwierzeck wrote:
> 
> > 2016-01-12 11:18 GMT+01:00 Purna Chandra Mandal <
> > purna.mandal at microchip.com>:
> > > Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
> > > ---
> > > 
> > > Changes in v3: None
> > > Changes in v2: None
> > > 
> > >  arch/mips/cpu/start.S | 2 ++
> > >  1 file changed, 2 insertions(+)
> > > 
> > > diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S
> > > index e95cdca..35d9650 100644
> > > --- a/arch/mips/cpu/start.S
> > > +++ b/arch/mips/cpu/start.S
> > > @@ -185,6 +185,8 @@ reset:
> > >         PTR_ADDU t0, k0, GD_MALLOC_BASE # gd->malloc_base offset
> > >         sw      sp, 0(t0)
> > >  #endif
> > > +       /* Initialize args to zero */
> > > +       move    a0, zero
> > the comment should be on the same line and more precise. That is
> > useful in disassemblies or when debugging. E.g.
> > 
> > move    a0, zero        # a0 <-- boot_flags = 0
> > 
> > Also add a commit message please explaining why the change is
> > required. Something like that the boot_flags of board_init_f should
> > be
> > set to 0 because $a0 may be utilized in lowlevel_init or
> > mips_cache_reset.
> 
> ack. Will add accordingly,
> 

can you send an updated version as separate patch promptly? I'd like to
apply this patch as soon as possible because I have some follow-up
patches for start.S. Thanks.

-- 
- Daniel

^ permalink raw reply	[flat|nested] 62+ messages in thread

end of thread, other threads:[~2016-01-21 14:06 UTC | newest]

Thread overview: 62+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-12 10:18 [U-Boot] [PATCH v3 00/14] Initial Microchip PIC32MZ[DA] Support Purna Chandra Mandal
2016-01-12 10:18 ` [U-Boot] [PATCH v3 01/14] MIPS: initialize board_init_f() argument to zero Purna Chandra Mandal
2016-01-12 12:29   ` Daniel Schwierzeck
2016-01-14  5:29     ` Purna Chandra Mandal
2016-01-21 14:06       ` Daniel Schwierzeck
2016-01-12 10:18 ` [U-Boot] [PATCH v3 02/14] MIPS: initial infrastructure for Microchip PIC32 architecture Purna Chandra Mandal
2016-01-12 12:55   ` Daniel Schwierzeck
2016-01-13 14:56   ` Tom Rini
2016-01-12 10:18 ` [U-Boot] [PATCH v3 03/14] drivers: clk: Add clock driver for Microchip PIC32 Microcontroller Purna Chandra Mandal
2016-01-13 13:38   ` Daniel Schwierzeck
2016-01-14  5:34     ` Purna Chandra Mandal
2016-01-13 14:55   ` Tom Rini
2016-01-14  6:04     ` Purna Chandra Mandal
2016-01-14 12:30       ` Tom Rini
2016-01-12 10:18 ` [U-Boot] [PATCH v3 04/14] drivers: pinctrl: Add pinctrl driver for Microchip PIC32 Purna Chandra Mandal
2016-01-13 13:42   ` Daniel Schwierzeck
2016-01-13 14:55   ` Tom Rini
2016-01-13 20:10   ` Simon Glass
2016-01-12 10:18 ` [U-Boot] [PATCH v3 05/14] drivers: gpio: add driver for Microchip PIC32 GPIO controller Purna Chandra Mandal
2016-01-13 13:46   ` Daniel Schwierzeck
2016-01-13 14:08     ` Daniel Schwierzeck
2016-01-14  5:41       ` Purna Chandra Mandal
2016-01-13 14:55   ` Tom Rini
2016-01-13 20:10   ` Simon Glass
2016-01-14 10:15     ` Purna Chandra Mandal
2016-01-12 10:18 ` [U-Boot] [PATCH v3 06/14] drivers: serial: add driver for Microchip PIC32 UART controller Purna Chandra Mandal
2016-01-13 13:49   ` Daniel Schwierzeck
2016-01-13 14:03     ` Daniel Schwierzeck
2016-01-14  5:42       ` Purna Chandra Mandal
2016-01-13 14:55   ` Tom Rini
2016-01-13 20:09   ` Simon Glass
2016-01-14  6:14     ` Purna Chandra Mandal
2016-01-12 10:18 ` [U-Boot] [PATCH v3 07/14] drivers: ddr: Add DDR2 SDRAM controller driver for Microchip PIC32 Purna Chandra Mandal
2016-01-13 13:53   ` Daniel Schwierzeck
2016-01-13 14:55   ` Tom Rini
2016-01-13 20:09   ` Simon Glass
2016-01-12 10:18 ` [U-Boot] [PATCH v3 08/14] MIPS: Add support for Microchip PIC32MZ[DA] SoC family Purna Chandra Mandal
2016-01-13 14:49   ` Daniel Schwierzeck
2016-01-14  5:54     ` Purna Chandra Mandal
2016-01-12 10:18 ` [U-Boot] [PATCH v3 09/14] board: Add Microchip PIC32MZ[DA]-Starter-Kit board Purna Chandra Mandal
2016-01-13 14:56   ` Tom Rini
2016-01-14  6:40     ` Purna Chandra Mandal
2016-01-13 15:03   ` Daniel Schwierzeck
2016-01-14  8:40     ` Purna Chandra Mandal
2016-01-12 10:18 ` [U-Boot] [PATCH v3 10/14] drivers: mmc: add driver for Microchip PIC32 SDHCI controller Purna Chandra Mandal
2016-01-13 14:56   ` Tom Rini
2016-01-13 15:15   ` Daniel Schwierzeck
2016-01-14  9:18     ` Purna Chandra Mandal
2016-01-12 10:18 ` [U-Boot] [PATCH v3 11/14] board: add SDHCI support for PIC32MZDASK board Purna Chandra Mandal
2016-01-13 14:56   ` Tom Rini
2016-01-14  8:31     ` Purna Chandra Mandal
2016-01-12 10:18 ` [U-Boot] [PATCH v3 12/14] drivers: net: phy: add SMSC LAN8740 Phy support Purna Chandra Mandal
2016-01-13 14:56   ` Tom Rini
2016-01-13 15:19   ` Daniel Schwierzeck
2016-01-12 10:18 ` [U-Boot] [PATCH v3 13/14] drivers: net: Add ethernet driver for Microchip PIC32 Purna Chandra Mandal
2016-01-13 14:56   ` Tom Rini
2016-01-14 10:29     ` Purna Chandra Mandal
2016-01-13 15:37   ` Daniel Schwierzeck
2016-01-14 10:05     ` Purna Chandra Mandal
2016-01-14 14:01       ` Daniel Schwierzeck
2016-01-12 10:18 ` [U-Boot] [PATCH v3 14/14] board: Enable ethernet, tftpboot support to pic32mzdask board Purna Chandra Mandal
2016-01-13 14:56   ` Tom Rini

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.