All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 05/28] i.MX: Add support for VF610 Tower board
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Add support for VF610 Tower board.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/boards/Makefile                           |   1 +
 arch/arm/boards/freescale-vf610-twr/Makefile       |   3 +
 .../flash-header-vf610-twr.imxcfg                  | 278 +++++++++++++++++++++
 arch/arm/boards/freescale-vf610-twr/lowlevel.c     |  45 ++++
 arch/arm/dts/Makefile                              |   1 +
 arch/arm/dts/vf610-twr.dts                         |  14 ++
 arch/arm/mach-imx/Kconfig                          |   4 +
 images/Makefile.imx                                |   5 +
 8 files changed, 351 insertions(+)
 create mode 100644 arch/arm/boards/freescale-vf610-twr/Makefile
 create mode 100644 arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
 create mode 100644 arch/arm/boards/freescale-vf610-twr/lowlevel.c
 create mode 100644 arch/arm/dts/vf610-twr.dts

diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
index 1a0f63f..ff0a86f 100644
--- a/arch/arm/boards/Makefile
+++ b/arch/arm/boards/Makefile
@@ -140,3 +140,4 @@ obj-$(CONFIG_MACH_ZYLONITE)			+= zylonite/
 obj-$(CONFIG_MACH_VARISCITE_MX6)		+= variscite-mx6/
 obj-$(CONFIG_MACH_VSCOM_BALTOS)			+= vscom-baltos/
 obj-$(CONFIG_MACH_QEMU_VIRT64)			+= qemu-virt64/
+obj-$(CONFIG_MACH_VF610_TWR)			+= freescale-vf610-twr/
diff --git a/arch/arm/boards/freescale-vf610-twr/Makefile b/arch/arm/boards/freescale-vf610-twr/Makefile
new file mode 100644
index 0000000..6b029ce
--- /dev/null
+++ b/arch/arm/boards/freescale-vf610-twr/Makefile
@@ -0,0 +1,3 @@
+obj-y += flash-header-vf610-twr.dcd.o
+extra-y += flash-header-vf610-twr.dcd.S flash-header-vf610-twr.dcd
+lwl-y += lowlevel.o
diff --git a/arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg b/arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
new file mode 100644
index 0000000..01ffc69
--- /dev/null
+++ b/arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
@@ -0,0 +1,278 @@
+soc vf610
+loadaddr 0x80000000
+dcdofs 0x400
+
+#define VF610_DDR_PAD_CTRL	0x00000180 /* 25 Ohm drive strength */
+#define VF610_DDR_PAD_CTRL_1	0x00010180 /* 25 Ohm drive strength + differential input */
+
+#define DDRMC_PHY_DQ_TIMING	0x00002613
+#define DDRMC_PHY_DQS_TIMING	0x00002615
+#define DDRMC_PHY_CTRL		0x00210000
+#define DDRMC_PHY_MASTER_CTRL	0x0001012a
+#define DDRMC_PHY_SLAVE_CTRL	0x00002000
+#define DDRMC_PHY_OFF		0x00000000
+#define DDRMC_PHY_PROC_PAD_ODT	0x00010101
+
+#ifdef DEBUG
+#define CHECKPOINT(n) wm 32 0x3f040000 n
+#else
+#define CHECKPOINT(n)
+#endif
+
+CHECKPOINT(1)
+
+/* ======================= Clock initialization =======================*/
+
+/*
+ * Ungate all IP block clocks
+ */
+wm 32 0x4006b040 0xffffffff
+wm 32 0x4006b044 0xffffffff
+wm 32 0x4006b048 0xffffffff
+wm 32 0x4006b04c 0xffffffff
+wm 32 0x4006b050 0xffffffff
+wm 32 0x4006b058 0xffffffff
+wm 32 0x4006b05c 0xffffffff
+wm 32 0x4006b060 0xffffffff
+wm 32 0x4006b064 0xffffffff
+wm 32 0x4006b068 0xffffffff
+wm 32 0x4006b06c 0xffffffff
+
+
+/*
+ * We have to options to clock DDR controller:
+ *
+ *  - Use Core-A5 clock
+ *  - Use PLL2 PFD2 clock
+ *
+
+ * Using first option without changing PLL settings doesn't seem to be
+ * possible given that DDRMC requires minimum of 300Mhz and MaskROM
+ * configures it to be clocked at 264Mhz. Changing PLL1 settings
+ * proved to be challenging becuase MaskROM code executing this DCD
+ * will also be fetching the rest of the bootloader via some
+ * peripheral interface whose clock is derived from Cortex-A5 clock.
+ *
+ * As a result this DCD configuration code uses the second option of
+ * clocking DDR wiht PLL2 PFD2 clock output
+ *
+ * Turn PLL2 on
+ */
+wm 32 0x40050030 0x00002001 /* Fout = Fin * 22 */
+
+CHECKPOINT(2)
+
+/*
+ * Wait for PLLs to lock
+ */
+check 32 while_any_bit_clear 0x40050030 0x80000000
+
+
+CHECKPOINT(3)
+
+/*
+ * Switch DDRMC to be clocked with PLL2 PFD2 and enable PFD2 output
+ */
+clear_bits 32 0x4006b008 0x00000040
+set_bits   32 0x4006b008 0x00002000
+
+
+
+/* ======================= DDR IOMUX ======================= */
+
+CHECKPOINT(4)
+
+wm 32 0x40048220 VF610_DDR_PAD_CTRL
+wm 32 0x40048224 VF610_DDR_PAD_CTRL
+wm 32 0x40048228 VF610_DDR_PAD_CTRL
+wm 32 0x4004822c VF610_DDR_PAD_CTRL
+wm 32 0x40048230 VF610_DDR_PAD_CTRL
+wm 32 0x40048234 VF610_DDR_PAD_CTRL
+wm 32 0x40048238 VF610_DDR_PAD_CTRL
+wm 32 0x4004823c VF610_DDR_PAD_CTRL
+wm 32 0x40048240 VF610_DDR_PAD_CTRL
+wm 32 0x40048244 VF610_DDR_PAD_CTRL
+wm 32 0x40048248 VF610_DDR_PAD_CTRL
+wm 32 0x4004824c VF610_DDR_PAD_CTRL
+wm 32 0x40048250 VF610_DDR_PAD_CTRL
+wm 32 0x40048254 VF610_DDR_PAD_CTRL
+wm 32 0x40048258 VF610_DDR_PAD_CTRL
+wm 32 0x4004825c VF610_DDR_PAD_CTRL
+wm 32 0x40048260 VF610_DDR_PAD_CTRL
+wm 32 0x40048264 VF610_DDR_PAD_CTRL
+wm 32 0x40048268 VF610_DDR_PAD_CTRL
+wm 32 0x4004826c VF610_DDR_PAD_CTRL
+wm 32 0x40048270 VF610_DDR_PAD_CTRL
+wm 32 0x40048274 VF610_DDR_PAD_CTRL
+wm 32 0x40048278 VF610_DDR_PAD_CTRL
+wm 32 0x4004827c VF610_DDR_PAD_CTRL_1
+wm 32 0x40048280 VF610_DDR_PAD_CTRL_1
+wm 32 0x40048284 VF610_DDR_PAD_CTRL_1
+wm 32 0x40048288 VF610_DDR_PAD_CTRL_1
+wm 32 0x4004828c VF610_DDR_PAD_CTRL_1
+wm 32 0x40048290 VF610_DDR_PAD_CTRL_1
+wm 32 0x40048294 VF610_DDR_PAD_CTRL_1
+wm 32 0x40048298 VF610_DDR_PAD_CTRL_1
+wm 32 0x4004829c VF610_DDR_PAD_CTRL_1
+wm 32 0x400482a0 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482a4 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482a8 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482ac VF610_DDR_PAD_CTRL_1
+wm 32 0x400482b0 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482b4 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482b8 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482bc VF610_DDR_PAD_CTRL_1
+wm 32 0x400482c0 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482c4 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482c8 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482cc VF610_DDR_PAD_CTRL
+wm 32 0x400482d0 VF610_DDR_PAD_CTRL
+wm 32 0x400482d4 VF610_DDR_PAD_CTRL
+wm 32 0x400482d8 VF610_DDR_PAD_CTRL
+wm 32 0x4004821c VF610_DDR_PAD_CTRL
+
+/* ======================= DDR Controller =======================*/
+
+CHECKPOINT(5)
+
+wm 32 0x400ae000 0x00000600
+wm 32 0x400ae008 0x00000020
+wm 32 0x400ae028 0x00013880
+wm 32 0x400ae02c 0x00030d40
+wm 32 0x400ae030 0x0000050c
+wm 32 0x400ae034 0x15040400
+wm 32 0x400ae038 0x1406040f
+wm 32 0x400ae040 0x04040000
+wm 32 0x400ae044 0x006db00c
+wm 32 0x400ae048 0x00000403
+wm 32 0x400ae050 0x01000000
+wm 32 0x400ae054 0x00060001
+wm 32 0x400ae058 0x000c0000
+wm 32 0x400ae05c 0x03000200
+wm 32 0x400ae060 0x00000006
+wm 32 0x400ae064 0x00010000
+wm 32 0x400ae068 0x0c30002c
+wm 32 0x400ae070 0x00000000
+wm 32 0x400ae074 0x00000003
+wm 32 0x400ae078 0x0000000a
+wm 32 0x400ae07c 0x003001d4
+wm 32 0x400ae084 0x00010000
+wm 32 0x400ae088 0x00050500
+wm 32 0x400ae098 0x00000000
+wm 32 0x400ae09c 0x04001002
+wm 32 0x400ae0a4 0x00000001
+wm 32 0x400ae0c0 0x00460420
+wm 32 0x400ae108 0x01000200
+wm 32 0x400ae10c 0x00000040
+wm 32 0x400ae114 0x00000200
+wm 32 0x400ae118 0x00000040
+wm 32 0x400ae120 0x00000000
+wm 32 0x400ae124 0x0a010300
+wm 32 0x400ae128 0x01014040
+wm 32 0x400ae12c 0x01010101
+wm 32 0x400ae130 0x03030100
+wm 32 0x400ae134 0x01000101
+wm 32 0x400ae138 0x0700000c
+wm 32 0x400ae13c 0x00000000
+wm 32 0x400ae148 0x10000000
+wm 32 0x400ae15c 0x01000000
+wm 32 0x400ae160 0x00040000
+wm 32 0x400ae164 0x00000002
+wm 32 0x400ae16c 0x00020000
+wm 32 0x400ae180 0x00002819
+wm 32 0x400ae184 0x01000000
+wm 32 0x400ae188 0x00000000
+wm 32 0x400ae18c 0x00000000
+wm 32 0x400ae198 0x00010100
+wm 32 0x400ae1a4 0x00000000
+wm 32 0x400ae1a8 0x00000004
+wm 32 0x400ae1b8 0x00040000
+wm 32 0x400ae1c8 0x00000000
+wm 32 0x400ae1cc 0x00000000
+wm 32 0x400ae1d4 0x00000000
+wm 32 0x400ae1d8 0x01010000
+wm 32 0x400ae1e0 0x02020000
+wm 32 0x400ae1e4 0x00000202
+wm 32 0x400ae1e8 0x01010064
+wm 32 0x400ae1ec 0x00010101
+wm 32 0x400ae1f0 0x00000064
+wm 32 0x400ae1f8 0x00000800
+wm 32 0x400ae210 0x00000506
+wm 32 0x400ae224 0x00020000
+wm 32 0x400ae228 0x01000000
+wm 32 0x400ae22c 0x04070303
+wm 32 0x400ae230 0x00000040
+wm 32 0x400ae23c 0x06000080
+wm 32 0x400ae240 0x04070303
+wm 32 0x400ae244 0x00000040
+wm 32 0x400ae248 0x00000040
+wm 32 0x400ae24c 0x000f0000
+wm 32 0x400ae250 0x000f0000
+wm 32 0x400ae25c 0x00000101
+wm 32 0x400ae268 0x682c4000
+wm 32 0x400ae26c 0x00000012
+wm 32 0x400ae278 0x00000006
+wm 32 0x400ae284 0x00010202
+
+/* ======================= DDR PHY =======================*/
+
+CHECKPOINT(6)
+
+wm 32 0x400ae400 DDRMC_PHY_DQ_TIMING
+wm 32 0x400ae440 DDRMC_PHY_DQ_TIMING
+wm 32 0x400ae480 DDRMC_PHY_DQ_TIMING
+wm 32 0x400ae404 DDRMC_PHY_DQS_TIMING
+wm 32 0x400ae444 DDRMC_PHY_DQS_TIMING
+wm 32 0x400ae408 DDRMC_PHY_CTRL
+wm 32 0x400ae448 DDRMC_PHY_CTRL
+wm 32 0x400ae488 DDRMC_PHY_CTRL
+wm 32 0x400ae40c DDRMC_PHY_MASTER_CTRL
+wm 32 0x400ae44c DDRMC_PHY_MASTER_CTRL
+wm 32 0x400ae48c DDRMC_PHY_MASTER_CTRL
+wm 32 0x400ae410 DDRMC_PHY_SLAVE_CTRL
+wm 32 0x400ae450 DDRMC_PHY_SLAVE_CTRL
+wm 32 0x400ae490 DDRMC_PHY_SLAVE_CTRL
+wm 32 0x400ae4c4 DDRMC_PHY_OFF
+wm 32 0x400ae4c8 0x00001100
+wm 32 0x400ae4d0 DDRMC_PHY_PROC_PAD_ODT
+
+wm 32 0x400ae000 0x00000601
+
+CHECKPOINT(7)
+
+check 32 while_any_bit_clear 0x400ae140 0x100
+
+CHECKPOINT(8)
+
+/*
+ * Cargo cult DDR controller initialization here we come!
+ *
+ * Experemintation with VF610 Tower Board shows that without the
+ * following code the board would not boot off of SD card when
+ * power-cycled. It will however happily boot when reset via SW3/Reset
+ * button. For whatever reason the following actions appear to be
+ * necessary:
+ *
+ *          - Initialize DDRMC as usual
+ *	    - Issue a read to location in DDR address space
+ *	    - Disable DDRMC
+ *	    - Enable DDRMC and wait for it to finish initializing
+ *
+ * I am sure this is all going to be extrememly embarrassing to read
+ * if/when the real problem and real solution is found.
+ */
+
+/*
+ * Because there's no standalone read command what we do here instead
+ * is write a pattern to memory and then checking that memory address
+ * against that pattern
+ */
+wm 32 0x80000000 0xa5a5a5a5
+check 32 while_any_bit_clear 0x80000000 0xa5a5a5a5
+
+wm 32 0x400ae000 0x00000600
+wm 32 0x400ae000 0x00000601
+
+check 32 while_any_bit_clear 0x400ae140 0x100
+
+CHECKPOINT(9)
\ No newline at end of file
diff --git a/arch/arm/boards/freescale-vf610-twr/lowlevel.c b/arch/arm/boards/freescale-vf610-twr/lowlevel.c
new file mode 100644
index 0000000..6504273
--- /dev/null
+++ b/arch/arm/boards/freescale-vf610-twr/lowlevel.c
@@ -0,0 +1,45 @@
+#include <common.h>
+#include <linux/sizes.h>
+#include <mach/generic.h>
+#include <asm/barebox-arm-head.h>
+#include <asm/barebox-arm.h>
+#include <mach/vf610-regs.h>
+#include <mach/clock-vf610.h>
+#include <mach/iomux-vf610.h>
+#include <debug_ll.h>
+
+static inline void setup_uart(void)
+{
+	void __iomem *iomuxbase = IOMEM(VF610_IOMUXC_BASE_ADDR);
+
+	vf610_ungate_all_peripherals();
+
+	/*
+	 * VF610_PAD_PTB4__UART1_TX
+	 */
+	writel(VF610_UART_PAD_CTRL | (2 << 20), iomuxbase + 0x0068);
+	writel(0, iomuxbase + 0x0380);
+
+	vf610_uart_setup_ll();
+}
+
+extern char __dtb_vf610_twr_start[];
+
+ENTRY_FUNCTION(start_vf610_twr, r0, r1, r2)
+{
+	int i;
+	void *fdt;
+	void __iomem *mscm = IOMEM(VF610_MSCM_BASE_ADDR);
+
+	vf610_cpu_lowlevel_init();
+
+	for (i = 0; i < VF610_MSCM_IRSPRC_NUM; i++)
+		writew(VF610_MSCM_IRSPRC_CP0_EN,
+		       mscm + VF610_MSCM_IRSPRC(i));
+
+	if (IS_ENABLED(CONFIG_DEBUG_LL))
+		setup_uart();
+
+	fdt = __dtb_vf610_twr_start - get_runtime_offset();
+	barebox_arm_entry(0x80000000, SZ_128M, fdt);
+}
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 8d8d1fb..607c620 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -78,5 +78,6 @@ pbl-dtb-$(CONFIG_MACH_UDOO) += imx6q-udoo.dtb.o
 pbl-dtb-$(CONFIG_MACH_USI_TOPKICK) += kirkwood-topkick-bb.dtb.o
 pbl-dtb-$(CONFIG_MACH_VARISCITE_MX6) += imx6q-var-custom.dtb.o
 pbl-dtb-$(CONFIG_MACH_VSCOM_BALTOS) += am335x-baltos-minimal.dtb.o
+pbl-dtb-$(CONFIG_MACH_VF610_TWR) += vf610-twr.dtb.o
 
 clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts *.dtb.lzo
diff --git a/arch/arm/dts/vf610-twr.dts b/arch/arm/dts/vf610-twr.dts
new file mode 100644
index 0000000..54b4435
--- /dev/null
+++ b/arch/arm/dts/vf610-twr.dts
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <arm/vf610-twr.dts>
+
+&usbdev0 {
+	status = "disabled";
+};
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index cfbaaa2..5f4fdc6 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -337,6 +337,10 @@ config MACH_CM_FX6
 	bool "CM FX6"
 	select ARCH_IMX6
 
+config MACH_VF610_TWR
+	bool "Freescale VF610 Tower Board"
+	select ARCH_VF610
+
 endif
 
 # ----------------------------------------------------------
diff --git a/images/Makefile.imx b/images/Makefile.imx
index 8db9c75..983d896 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -403,3 +403,8 @@ pblx-$(CONFIG_MACH_ELTEC_HIPERCAM) += start_imx6dl_eltec_hipercam
 CFG_start_imx6dl_eltec_hipercam.pblx.imximg = $(board)/eltec-hipercam/flash-header-eltec-hipercam.imxcfg
 FILE_barebox-eltec-hipercam.img = start_imx6dl_eltec_hipercam.pblx.imximg
 image-$(CONFIG_MACH_ELTEC_HIPERCAM) += barebox-eltec-hipercam.img
+
+pblx-$(CONFIG_MACH_VF610_TWR) += start_vf610_twr
+CFG_start_vf610_twr.pblx.imximg = $(board)/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
+FILE_barebox-vf610-twr.img = start_vf610_twr.pblx.imximg
+image-$(CONFIG_MACH_VF610_TWR) += barebox-vf610-twr.img
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 09/28] clk: Port of_clk_set_defaults()
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Port of_clk_set_defautls() from Linux kernel in order to support DT
configurations that require it (e. g. Vybrid).

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/clk/Makefile         |   2 +-
 drivers/clk/clk-conf.c       | 144 +++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/clk.c            |   2 +
 include/linux/clk/clk-conf.h |  14 +++++
 4 files changed, 161 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/clk-conf.c
 create mode 100644 include/linux/clk/clk-conf.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 47ed7b1..0fe8f1e 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,6 +1,6 @@
 obj-$(CONFIG_COMMON_CLK)	+= clk.o clk-fixed.o clk-divider.o clk-fixed-factor.o \
 				clk-mux.o clk-gate.o clk-composite.o \
-				clk-fractional-divider.o
+				clk-fractional-divider.o clk-conf.o
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
 
 obj-$(CONFIG_ARCH_MVEBU)	+= mvebu/
diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
new file mode 100644
index 0000000..961fad8
--- /dev/null
+++ b/drivers/clk/clk-conf.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd.
+ * Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <io.h>
+#include <malloc.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/clk/clk-conf.h>
+
+static int __set_clk_parents(struct device_node *node, bool clk_supplier)
+{
+	struct of_phandle_args clkspec;
+	int index, rc, num_parents;
+	struct clk *clk, *pclk;
+
+	num_parents = of_count_phandle_with_args(node, "assigned-clock-parents",
+						 "#clock-cells");
+	if (num_parents == -EINVAL)
+		pr_err("clk: invalid value of clock-parents property at %s\n",
+		       node->full_name);
+
+	for (index = 0; index < num_parents; index++) {
+		rc = of_parse_phandle_with_args(node, "assigned-clock-parents",
+					"#clock-cells",	index, &clkspec);
+		if (rc < 0) {
+			/* skip empty (null) phandles */
+			if (rc == -ENOENT)
+				continue;
+			else
+				return rc;
+		}
+		if (clkspec.np == node && !clk_supplier)
+			return 0;
+		pclk = of_clk_get_from_provider(&clkspec);
+		if (IS_ERR(pclk)) {
+			pr_warn("clk: couldn't get parent clock %d for %s\n",
+				index, node->full_name);
+			return PTR_ERR(pclk);
+		}
+
+		rc = of_parse_phandle_with_args(node, "assigned-clocks",
+					"#clock-cells", index, &clkspec);
+		if (rc < 0)
+			goto err;
+		if (clkspec.np == node && !clk_supplier) {
+			rc = 0;
+			goto err;
+		}
+		clk = of_clk_get_from_provider(&clkspec);
+		if (IS_ERR(clk)) {
+			pr_warn("clk: couldn't get parent clock %d for %s\n",
+				index, node->full_name);
+			rc = PTR_ERR(clk);
+			goto err;
+		}
+
+		rc = clk_set_parent(clk, pclk);
+		if (rc < 0)
+			pr_err("clk: failed to reparent %s to %s: %d\n",
+			       __clk_get_name(clk), __clk_get_name(pclk), rc);
+		clk_put(clk);
+		clk_put(pclk);
+	}
+	return 0;
+err:
+	clk_put(pclk);
+	return rc;
+}
+
+static int __set_clk_rates(struct device_node *node, bool clk_supplier)
+{
+	struct of_phandle_args clkspec;
+	struct property	*prop;
+	const __be32 *cur;
+	int rc, index = 0;
+	struct clk *clk;
+	u32 rate;
+
+	of_property_for_each_u32(node, "assigned-clock-rates", prop, cur, rate) {
+		if (rate) {
+			rc = of_parse_phandle_with_args(node, "assigned-clocks",
+					"#clock-cells",	index, &clkspec);
+			if (rc < 0) {
+				/* skip empty (null) phandles */
+				if (rc == -ENOENT)
+					continue;
+				else
+					return rc;
+			}
+			if (clkspec.np == node && !clk_supplier)
+				return 0;
+
+			clk = of_clk_get_from_provider(&clkspec);
+			if (IS_ERR(clk)) {
+				pr_warn("clk: couldn't get clock %d for %s\n",
+					index, node->full_name);
+				return PTR_ERR(clk);
+			}
+
+			rc = clk_set_rate(clk, rate);
+			if (rc < 0)
+				pr_err("clk: couldn't set %s clk rate to %d (%d), current rate: %ld\n",
+				       __clk_get_name(clk), rate, rc,
+				       clk_get_rate(clk));
+			clk_put(clk);
+		}
+		index++;
+	}
+	return 0;
+}
+
+/**
+ * of_clk_set_defaults() - parse and set assigned clocks configuration
+ * @node: device node to apply clock settings for
+ * @clk_supplier: true if clocks supplied by @node should also be considered
+ *
+ * This function parses 'assigned-{clocks/clock-parents/clock-rates}' properties
+ * and sets any specified clock parents and rates. The @clk_supplier argument
+ * should be set to true if @node may be also a clock supplier of any clock
+ * listed in its 'assigned-clocks' or 'assigned-clock-parents' properties.
+ * If @clk_supplier is false the function exits returning 0 as soon as it
+ * determines the @node is also a supplier of any of the clocks.
+ */
+int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
+{
+	int rc;
+
+	if (!node)
+		return 0;
+
+	rc = __set_clk_parents(node, clk_supplier);
+	if (rc < 0)
+		return rc;
+
+	return __set_clk_rates(node, clk_supplier);
+}
+EXPORT_SYMBOL_GPL(of_clk_set_defaults);
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index a38f339..28a1be5 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -19,6 +19,7 @@
 #include <malloc.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/clk/clk-conf.h>
 
 static LIST_HEAD(clks);
 
@@ -525,6 +526,7 @@ int of_clk_init(struct device_node *root, const struct of_device_id *matches)
 			if (force || parent_ready(clk_provider->np)) {
 
 				clk_provider->clk_init_cb(clk_provider->np);
+				of_clk_set_defaults(clk_provider->np, true);
 
 				list_del(&clk_provider->node);
 				free(clk_provider);
diff --git a/include/linux/clk/clk-conf.h b/include/linux/clk/clk-conf.h
new file mode 100644
index 0000000..0b8a973
--- /dev/null
+++ b/include/linux/clk/clk-conf.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd.
+ * Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/types.h>
+
+struct device_node;
+int of_clk_set_defaults(struct device_node *node, bool clk_supplier);
+
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 03/28] i.MX: Add DEBUG_LL hooks for VF610
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Add code to support DEBUG_LL functionality on VF610/Vybrid platform.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/mach-imx/include/mach/debug_ll.h |  27 ++-
 common/Kconfig                            |  10 +-
 include/serial/lpuart.h                   | 281 ++++++++++++++++++++++++++++++
 3 files changed, 316 insertions(+), 2 deletions(-)
 create mode 100644 include/serial/lpuart.h

diff --git a/arch/arm/mach-imx/include/mach/debug_ll.h b/arch/arm/mach-imx/include/mach/debug_ll.h
index 5c2db6c..a132f3c 100644
--- a/arch/arm/mach-imx/include/mach/debug_ll.h
+++ b/arch/arm/mach-imx/include/mach/debug_ll.h
@@ -14,8 +14,10 @@
 #include <mach/imx51-regs.h>
 #include <mach/imx53-regs.h>
 #include <mach/imx6-regs.h>
+#include <mach/vf610-regs.h>
 
 #include <serial/imx-uart.h>
+#include <serial/lpuart.h>
 
 #ifdef CONFIG_DEBUG_LL
 
@@ -42,6 +44,8 @@
 #define IMX_DEBUG_SOC MX53
 #elif defined CONFIG_DEBUG_IMX6Q_UART
 #define IMX_DEBUG_SOC MX6
+#elif defined CONFIG_DEBUG_VF610_UART
+#define IMX_DEBUG_SOC VF610
 #else
 #error "unknown i.MX debug uart soc type"
 #endif
@@ -74,6 +78,13 @@ static inline void imx6_uart_setup_ll(void)
 	imx6_uart_setup(base);
 }
 
+static inline void vf610_uart_setup_ll(void)
+{
+	void *base = IOMEM(IMX_UART_BASE(IMX_DEBUG_SOC, CONFIG_DEBUG_IMX_UART_PORT));
+
+	lpuart_setup(base, 66000000);
+}
+
 static inline void PUTC_LL(int c)
 {
 	void __iomem *base = IOMEM(IMX_UART_BASE(IMX_DEBUG_SOC,
@@ -82,14 +93,19 @@ static inline void PUTC_LL(int c)
 	if (!base)
 		return;
 
-	imx_uart_putc(base, c);
+	if (IS_ENABLED(CONFIG_DEBUG_VF610_UART))
+		lpuart_putc(base, c);
+	else
+		imx_uart_putc(base, c);
 }
+
 #else
 
 static inline void imx50_uart_setup_ll(void) {}
 static inline void imx51_uart_setup_ll(void) {}
 static inline void imx53_uart_setup_ll(void) {}
 static inline void imx6_uart_setup_ll(void)  {}
+static inline void vf610_uart_setup_ll(void) {}
 
 #endif /* CONFIG_DEBUG_LL */
 
@@ -115,4 +131,13 @@ static inline void imx53_ungate_all_peripherals(void)
 	imx_ungate_all_peripherals(IOMEM(MX53_CCM_BASE_ADDR));
 }
 
+static inline void vf610_ungate_all_peripherals(void)
+{
+	void __iomem *ccmbase = IOMEM(VF610_CCM_BASE_ADDR);
+	int i;
+
+	for (i = 0x40; i <= 0x6c; i += 4)
+		writel(0xffffffff, ccmbase + i);
+}
+
 #endif /* __MACH_DEBUG_LL_H__ */
diff --git a/common/Kconfig b/common/Kconfig
index efd1949..ed472a0 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1071,6 +1071,13 @@ config DEBUG_IMX6Q_UART
 	  Say Y here if you want kernel low-level debugging support
 	  on i.MX6Q.
 
+config DEBUG_VF610_UART
+	bool "VF610 Debug UART"
+	depends on ARCH_VF610
+	help
+	  Say Y here if you want kernel low-level debugging support
+	  on VF610.
+
 config DEBUG_OMAP3_UART
 	bool "OMAP3 Debug UART"
 	depends on ARCH_OMAP3
@@ -1111,7 +1118,8 @@ config DEBUG_IMX_UART_PORT
 						DEBUG_IMX51_UART || \
 						DEBUG_IMX53_UART || \
 						DEBUG_IMX6Q_UART || \
-						DEBUG_IMX6SL_UART
+						DEBUG_IMX6SL_UART || \
+						DEBUG_VF610_UART
 	default 1
 	depends on ARCH_IMX
 	help
diff --git a/include/serial/lpuart.h b/include/serial/lpuart.h
new file mode 100644
index 0000000..917f644
--- /dev/null
+++ b/include/serial/lpuart.h
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2016 Zodiac Inflight Innovation
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
+ *
+ * Based on code found in Linux kernel and U-Boot.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __LPUART_H__
+#define __LPUART_H__
+
+
+/* All registers are 8-bit width */
+#define UARTBDH			0x00
+#define UARTBDL			0x01
+#define UARTCR1			0x02
+#define UARTCR2			0x03
+#define UARTSR1			0x04
+#define UARTCR3			0x06
+#define UARTDR			0x07
+#define UARTCR4			0x0a
+#define UARTCR5			0x0b
+#define UARTMODEM		0x0d
+#define UARTPFIFO		0x10
+#define UARTCFIFO		0x11
+#define UARTSFIFO		0x12
+#define UARTTWFIFO		0x13
+#define UARTTCFIFO		0x14
+#define UARTRWFIFO		0x15
+#define UARTRCFIFO		0x16
+
+#define UARTBDH_LBKDIE		0x80
+#define UARTBDH_RXEDGIE		0x40
+#define UARTBDH_SBR_MASK	0x1f
+
+#define UARTCR1_LOOPS		0x80
+#define UARTCR1_RSRC		0x20
+#define UARTCR1_M		0x10
+#define UARTCR1_WAKE		0x08
+#define UARTCR1_ILT		0x04
+#define UARTCR1_PE		0x02
+#define UARTCR1_PT		0x01
+
+#define UARTCR2_TIE		0x80
+#define UARTCR2_TCIE		0x40
+#define UARTCR2_RIE		0x20
+#define UARTCR2_ILIE		0x10
+#define UARTCR2_TE		0x08
+#define UARTCR2_RE		0x04
+#define UARTCR2_RWU		0x02
+#define UARTCR2_SBK		0x01
+
+#define UARTSR1_TDRE		0x80
+#define UARTSR1_TC		0x40
+#define UARTSR1_RDRF		0x20
+#define UARTSR1_IDLE		0x10
+#define UARTSR1_OR		0x08
+#define UARTSR1_NF		0x04
+#define UARTSR1_FE		0x02
+#define UARTSR1_PE		0x01
+
+#define UARTCR3_R8		0x80
+#define UARTCR3_T8		0x40
+#define UARTCR3_TXDIR		0x20
+#define UARTCR3_TXINV		0x10
+#define UARTCR3_ORIE		0x08
+#define UARTCR3_NEIE		0x04
+#define UARTCR3_FEIE		0x02
+#define UARTCR3_PEIE		0x01
+
+#define UARTCR4_MAEN1		0x80
+#define UARTCR4_MAEN2		0x40
+#define UARTCR4_M10		0x20
+#define UARTCR4_BRFA_MASK	0x1f
+#define UARTCR4_BRFA_OFF	0
+
+#define UARTCR5_TDMAS		0x80
+#define UARTCR5_RDMAS		0x20
+
+#define UARTMODEM_RXRTSE	0x08
+#define UARTMODEM_TXRTSPOL	0x04
+#define UARTMODEM_TXRTSE	0x02
+#define UARTMODEM_TXCTSE	0x01
+
+#define UARTPFIFO_TXFE		0x80
+#define UARTPFIFO_FIFOSIZE_MASK	0x7
+#define UARTPFIFO_TXSIZE_OFF	4
+#define UARTPFIFO_RXFE		0x08
+#define UARTPFIFO_RXSIZE_OFF	0
+
+#define UARTCFIFO_TXFLUSH	0x80
+#define UARTCFIFO_RXFLUSH	0x40
+#define UARTCFIFO_RXOFE		0x04
+#define UARTCFIFO_TXOFE		0x02
+#define UARTCFIFO_RXUFE		0x01
+
+#define UARTSFIFO_TXEMPT	0x80
+#define UARTSFIFO_RXEMPT	0x40
+#define UARTSFIFO_RXOF		0x04
+#define UARTSFIFO_TXOF		0x02
+#define UARTSFIFO_RXUF		0x01
+
+/* 32-bit register defination */
+#define UARTBAUD		0x00
+#define UARTSTAT		0x04
+#define UARTCTRL		0x08
+#define UARTDATA		0x0C
+#define UARTMATCH		0x10
+#define UARTMODIR		0x14
+#define UARTFIFO		0x18
+#define UARTWATER		0x1c
+
+#define UARTBAUD_MAEN1		0x80000000
+#define UARTBAUD_MAEN2		0x40000000
+#define UARTBAUD_M10		0x20000000
+#define UARTBAUD_TDMAE		0x00800000
+#define UARTBAUD_RDMAE		0x00200000
+#define UARTBAUD_MATCFG		0x00400000
+#define UARTBAUD_BOTHEDGE	0x00020000
+#define UARTBAUD_RESYNCDIS	0x00010000
+#define UARTBAUD_LBKDIE		0x00008000
+#define UARTBAUD_RXEDGIE	0x00004000
+#define UARTBAUD_SBNS		0x00002000
+#define UARTBAUD_SBR		0x00000000
+#define UARTBAUD_SBR_MASK	0x1fff
+
+#define UARTSTAT_LBKDIF		0x80000000
+#define UARTSTAT_RXEDGIF	0x40000000
+#define UARTSTAT_MSBF		0x20000000
+#define UARTSTAT_RXINV		0x10000000
+#define UARTSTAT_RWUID		0x08000000
+#define UARTSTAT_BRK13		0x04000000
+#define UARTSTAT_LBKDE		0x02000000
+#define UARTSTAT_RAF		0x01000000
+#define UARTSTAT_TDRE		0x00800000
+#define UARTSTAT_TC		0x00400000
+#define UARTSTAT_RDRF		0x00200000
+#define UARTSTAT_IDLE		0x00100000
+#define UARTSTAT_OR		0x00080000
+#define UARTSTAT_NF		0x00040000
+#define UARTSTAT_FE		0x00020000
+#define UARTSTAT_PE		0x00010000
+#define UARTSTAT_MA1F		0x00008000
+#define UARTSTAT_M21F		0x00004000
+
+#define UARTCTRL_R8T9		0x80000000
+#define UARTCTRL_R9T8		0x40000000
+#define UARTCTRL_TXDIR		0x20000000
+#define UARTCTRL_TXINV		0x10000000
+#define UARTCTRL_ORIE		0x08000000
+#define UARTCTRL_NEIE		0x04000000
+#define UARTCTRL_FEIE		0x02000000
+#define UARTCTRL_PEIE		0x01000000
+#define UARTCTRL_TIE		0x00800000
+#define UARTCTRL_TCIE		0x00400000
+#define UARTCTRL_RIE		0x00200000
+#define UARTCTRL_ILIE		0x00100000
+#define UARTCTRL_TE		0x00080000
+#define UARTCTRL_RE		0x00040000
+#define UARTCTRL_RWU		0x00020000
+#define UARTCTRL_SBK		0x00010000
+#define UARTCTRL_MA1IE		0x00008000
+#define UARTCTRL_MA2IE		0x00004000
+#define UARTCTRL_IDLECFG	0x00000100
+#define UARTCTRL_LOOPS		0x00000080
+#define UARTCTRL_DOZEEN		0x00000040
+#define UARTCTRL_RSRC		0x00000020
+#define UARTCTRL_M		0x00000010
+#define UARTCTRL_WAKE		0x00000008
+#define UARTCTRL_ILT		0x00000004
+#define UARTCTRL_PE		0x00000002
+#define UARTCTRL_PT		0x00000001
+
+#define UARTDATA_NOISY		0x00008000
+#define UARTDATA_PARITYE	0x00004000
+#define UARTDATA_FRETSC		0x00002000
+#define UARTDATA_RXEMPT		0x00001000
+#define UARTDATA_IDLINE		0x00000800
+#define UARTDATA_MASK		0x3ff
+
+#define UARTMODIR_IREN		0x00020000
+#define UARTMODIR_TXCTSSRC	0x00000020
+#define UARTMODIR_TXCTSC	0x00000010
+#define UARTMODIR_RXRTSE	0x00000008
+#define UARTMODIR_TXRTSPOL	0x00000004
+#define UARTMODIR_TXRTSE	0x00000002
+#define UARTMODIR_TXCTSE	0x00000001
+
+#define UARTFIFO_TXEMPT		0x00800000
+#define UARTFIFO_RXEMPT		0x00400000
+#define UARTFIFO_TXOF		0x00020000
+#define UARTFIFO_RXUF		0x00010000
+#define UARTFIFO_TXFLUSH	0x00008000
+#define UARTFIFO_RXFLUSH	0x00004000
+#define UARTFIFO_TXOFE		0x00000200
+#define UARTFIFO_RXUFE		0x00000100
+#define UARTFIFO_TXFE		0x00000080
+#define UARTFIFO_FIFOSIZE_MASK	0x7
+#define UARTFIFO_TXSIZE_OFF	4
+#define UARTFIFO_RXFE		0x00000008
+#define UARTFIFO_RXSIZE_OFF	0
+
+#define UARTWATER_COUNT_MASK	0xff
+#define UARTWATER_TXCNT_OFF	8
+#define UARTWATER_RXCNT_OFF	24
+#define UARTWATER_WATER_MASK	0xff
+#define UARTWATER_TXWATER_OFF	0
+#define UARTWATER_RXWATER_OFF	16
+
+#define FSL_UART_RX_DMA_BUFFER_SIZE	64
+
+static inline void lpuart_setbrg(void __iomem *base,
+				 unsigned int refclock,
+				 unsigned int baudrate)
+{
+	unsigned int bfra;
+	u16 sbr;
+
+	sbr = (u16) (refclock / (16 * baudrate));
+
+	writeb(sbr >> 8,   base + UARTBDH);
+	writeb(sbr & 0xff, base + UARTBDL);
+
+	bfra  = DIV_ROUND_UP(2 * refclock, baudrate) - 32 * sbr;
+	bfra &= UARTCR4_BRFA_MASK;
+	writeb(bfra, base + UARTCR4);
+}
+
+static inline void lpuart_setup_with_fifo(void __iomem *base,
+					  unsigned int refclock,
+					  unsigned int twfifo)
+{
+	/* Disable UART */
+	writeb(0, base + UARTCR2);
+	writeb(0, base + UARTMODEM);
+	writeb(0, base + UARTCR1);
+
+	if (twfifo) {
+		writeb(UARTPFIFO_TXFE | UARTPFIFO_RXFE, base + UARTPFIFO);
+		writeb((u8)twfifo, base + UARTTWFIFO);
+	} else {
+		writeb(0, base + UARTPFIFO);
+		writeb(0, base + UARTTWFIFO);
+	}
+	writeb(1, base + UARTRWFIFO);
+	writeb(UARTCFIFO_RXFLUSH | UARTCFIFO_TXFLUSH, base + UARTCFIFO);
+
+	lpuart_setbrg(base, refclock, CONFIG_BAUDRATE);
+
+	writeb(UARTCR2_TE | UARTCR2_RE, base + UARTCR2);
+}
+
+static inline void lpuart_setup(void __iomem *base,
+				unsigned int refclock)
+{
+	lpuart_setup_with_fifo(base, refclock, 0x00);
+}
+
+static inline void lpuart_putc(void __iomem *base, int c)
+{
+	if (!(readb(base + UARTCR2) & UARTCR2_TE))
+		return;
+
+	while (!(readb(base + UARTSR1) & UARTSR1_TDRE));
+
+	writeb(c, base + UARTDR);
+}
+
+#endif
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 08/28] clk: Port clock dependency resolution code
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Port the clock dependency resolution algorithm utilized by Linux
kernel's version of of_clk_init(), to allow for SoCs whose DT clock
configuration reqires such behaviour for correct initialization (Vybrid
is one such example).

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/clk/clk.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 82 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 630a84d..a38f339 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -404,7 +404,7 @@ EXPORT_SYMBOL_GPL(of_clk_del_provider);
 struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec)
 {
 	struct of_clk_provider *provider;
-	struct clk *clk = ERR_PTR(-ENOENT);
+	struct clk *clk = ERR_PTR(-EPROBE_DEFER);
 
 	/* Check if we have such a provider in our array */
 	list_for_each_entry(provider, &of_clk_providers, link) {
@@ -437,6 +437,47 @@ char *of_clk_get_parent_name(struct device_node *np, unsigned int index)
 }
 EXPORT_SYMBOL_GPL(of_clk_get_parent_name);
 
+struct clock_provider {
+	of_clk_init_cb_t clk_init_cb;
+	struct device_node *np;
+	struct list_head node;
+};
+
+/*
+ * This function looks for a parent clock. If there is one, then it
+ * checks that the provider for this parent clock was initialized, in
+ * this case the parent clock will be ready.
+ */
+static int parent_ready(struct device_node *np)
+{
+	int i = 0;
+
+	while (true) {
+		struct clk *clk = of_clk_get(np, i);
+
+		/* this parent is ready we can check the next one */
+		if (!IS_ERR(clk)) {
+			clk_put(clk);
+			i++;
+			continue;
+		}
+
+		/* at least one parent is not ready, we exit now */
+		if (PTR_ERR(clk) == -EPROBE_DEFER)
+			return 0;
+
+		/*
+		 * Here we make assumption that the device tree is
+		 * written correctly. So an error means that there is
+		 * no more parent. As we didn't exit yet, then the
+		 * previous parent are ready. If there is no clock
+		 * parent, no need to wait for them, then we can
+		 * consider their absence as being ready
+		 */
+		return 1;
+	}
+}
+
 /**
  * of_clk_init() - Scan and init clock providers from the DT
  * @root: parent of the first level to probe or NULL for the root of the tree
@@ -449,8 +490,11 @@ EXPORT_SYMBOL_GPL(of_clk_get_parent_name);
  */
 int of_clk_init(struct device_node *root, const struct of_device_id *matches)
 {
+	struct clock_provider *clk_provider, *next;
+	bool is_init_done;
+	bool force = false;
+	LIST_HEAD(clk_provider_list);
 	const struct of_device_id *match;
-	int rc;
 
 	if (!root)
 		root = of_find_node_by_path("/");
@@ -459,12 +503,43 @@ int of_clk_init(struct device_node *root, const struct of_device_id *matches)
 	if (!matches)
 		matches = __clk_of_table_start;
 
+	/* First prepare the list of the clocks providers */
 	for_each_matching_node_and_match(root, matches, &match) {
-		of_clk_init_cb_t clk_init_cb = (of_clk_init_cb_t)match->data;
-		rc = clk_init_cb(root);
-		if (rc)
-			pr_err("%s: failed to init clock for %s: %d\n",
-			       __func__, root->full_name, rc);
+		struct clock_provider *parent;
+
+		if (!of_device_is_available(root))
+			continue;
+
+		parent = xzalloc(sizeof(*parent));
+
+		parent->clk_init_cb = match->data;
+		parent->np = root;
+		list_add_tail(&parent->node, &clk_provider_list);
+	}
+
+	while (!list_empty(&clk_provider_list)) {
+		is_init_done = false;
+		list_for_each_entry_safe(clk_provider, next,
+					 &clk_provider_list, node) {
+
+			if (force || parent_ready(clk_provider->np)) {
+
+				clk_provider->clk_init_cb(clk_provider->np);
+
+				list_del(&clk_provider->node);
+				free(clk_provider);
+				is_init_done = true;
+			}
+		}
+
+		/*
+		 * We didn't manage to initialize any of the
+		 * remaining providers during the last loop, so now we
+		 * initialize all the remaining ones unconditionally
+		 * in case the clock parent was not mandatory
+		 */
+		if (!is_init_done)
+			force = true;
 	}
 
 	return 0;
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 06/28] pinctrl: Add provisions to control GPIO pin direction
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Some SoC (of which Vybrid is a one example) relegate GPIO direction
control to their pinmux IP block, instead of having that functionality
within GPIO IP. Add provisions to control that aspect of pinmux to
support such SoCs.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/pinctrl/pinctrl.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 include/pinctrl.h         | 21 +++++++++++++++++++++
 2 files changed, 66 insertions(+)

diff --git a/drivers/pinctrl/pinctrl.c b/drivers/pinctrl/pinctrl.c
index e7b08a2..bef4fcd 100644
--- a/drivers/pinctrl/pinctrl.c
+++ b/drivers/pinctrl/pinctrl.c
@@ -24,6 +24,51 @@
 
 static LIST_HEAD(pinctrl_list);
 
+static struct pinctrl_device *pin_to_pinctrl(unsigned int pin)
+{
+	struct pinctrl_device *pinctrl;
+
+	list_for_each_entry(pinctrl, &pinctrl_list, list)
+		if (pin > pinctrl->base &&
+		    pin < pinctrl->base + pinctrl->npins)
+			return pinctrl;
+	return NULL;
+}
+
+static int pinctrl_gpio_direction(unsigned pin, bool input)
+{
+	struct pinctrl_device *pinctrl = pin_to_pinctrl(pin);
+
+	if (!pinctrl)
+		return -EINVAL;
+
+	BUG_ON(!pinctrl->ops->set_direction);
+
+	return pinctrl->ops->set_direction(pinctrl, pin, input);
+}
+
+int pinctrl_gpio_direction_input(unsigned int pin)
+{
+	return pinctrl_gpio_direction(pin, true);
+}
+
+int pinctrl_gpio_direction_output(unsigned int pin)
+{
+	return pinctrl_gpio_direction(pin, false);
+}
+
+int pinctrl_gpio_get_direction(unsigned pin)
+{
+	struct pinctrl_device *pinctrl = pin_to_pinctrl(pin);
+
+	if (!pinctrl)
+		return -EINVAL;
+
+	BUG_ON(!pinctrl->ops->get_direction);
+
+	return pinctrl->ops->get_direction(pinctrl, pin);
+}
+
 static struct pinctrl_device *find_pinctrl(struct device_node *node)
 {
 	struct pinctrl_device *pdev;
diff --git a/include/pinctrl.h b/include/pinctrl.h
index 0f03b10..0fde3f9 100644
--- a/include/pinctrl.h
+++ b/include/pinctrl.h
@@ -5,6 +5,8 @@ struct pinctrl_device;
 
 struct pinctrl_ops {
 	int (*set_state)(struct pinctrl_device *, struct device_node *);
+	int (*set_direction)(struct pinctrl_device *, unsigned int, bool);
+	int (*get_direction)(struct pinctrl_device *, unsigned int);
 };
 
 struct pinctrl_device {
@@ -12,6 +14,7 @@ struct pinctrl_device {
 	struct pinctrl_ops *ops;
 	struct list_head list;
 	struct device_node *node;
+	unsigned int base, npins;
 };
 
 int pinctrl_register(struct pinctrl_device *pdev);
@@ -22,6 +25,9 @@ int pinctrl_select_state(struct device_d *dev, const char *state);
 int pinctrl_select_state_default(struct device_d *dev);
 int of_pinctrl_select_state(struct device_node *np, const char *state);
 int of_pinctrl_select_state_default(struct device_node *np);
+int pinctrl_gpio_direction_input(unsigned pin);
+int pinctrl_gpio_direction_output(unsigned int pin);
+int pinctrl_gpio_get_direction(unsigned pin);
 #else
 static inline int pinctrl_select_state(struct device_d *dev, const char *state)
 {
@@ -42,6 +48,21 @@ static inline int of_pinctrl_select_state_default(struct device_node *np)
 {
 	return -ENODEV;
 }
+
+static inline int pinctrl_gpio_direction_input(unsigend pin)
+{
+	return -ENOTSUPP;
+}
+
+static inline int pinctrl_gpio_direction_output(unsigned int pin)
+{
+	return -ENOTSUPP;
+}
+
+static inline int pinctrl_gpio_get_direction(unsigned pin)
+{
+	return -ENOTSUPP;
+}
 #endif
 
 #endif /* PINCTRL_H */
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 04/28] i.MX: scripts: Add "vf610" soc to imx-image
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Needed in order to support Vybrid SoCs.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 scripts/imx/imx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/scripts/imx/imx.c b/scripts/imx/imx.c
index c8ee309..bd48321 100644
--- a/scripts/imx/imx.c
+++ b/scripts/imx/imx.c
@@ -223,6 +223,7 @@ static struct soc_type socs[] = {
 	{ .name = "imx51", .header_version = 1, .cpu_type = IMX_CPU_IMX51 },
 	{ .name = "imx53", .header_version = 2, .cpu_type = IMX_CPU_IMX53 },
 	{ .name = "imx6", .header_version = 2, .cpu_type = IMX_CPU_IMX6 },
+	{ .name = "vf610", .header_version = 2, .cpu_type = IMX_CPU_VF610 },
 };
 
 static int do_soc(struct config_data *data, int argc, char *argv[])
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 01/28] i.MX: Add primitive functions for VF610 family
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Add very basic functions to support VF610 family.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/mach-imx/Kconfig                      | 10 ++++++++++
 arch/arm/mach-imx/cpu_init.c                   |  5 +++++
 arch/arm/mach-imx/imx.c                        |  4 ++++
 arch/arm/mach-imx/include/mach/generic.h       | 13 +++++++++++++
 arch/arm/mach-imx/include/mach/imx_cpu_types.h |  1 +
 5 files changed, 33 insertions(+)

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index f23af99..cfbaaa2 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -149,6 +149,16 @@ config ARCH_IMX6SX
 	select OFTREE
 	select COMMON_CLK_OF_PROVIDER
 
+config ARCH_VF610
+	bool
+	select ARCH_HAS_L2X0
+	select ARCH_HAS_FEC_IMX
+	select CPU_V7
+	select PINCTRL
+	select OFTREE
+	select COMMON_CLK
+	select COMMON_CLK_OF_PROVIDER
+
 config IMX_MULTI_BOARDS
 	bool "Allow multiple boards to be selected"
 	select HAVE_PBL_MULTI_IMAGES
diff --git a/arch/arm/mach-imx/cpu_init.c b/arch/arm/mach-imx/cpu_init.c
index 7603883..6971d89 100644
--- a/arch/arm/mach-imx/cpu_init.c
+++ b/arch/arm/mach-imx/cpu_init.c
@@ -33,3 +33,8 @@ void imx6_cpu_lowlevel_init(void)
 	enable_arm_errata_794072_war();
 	enable_arm_errata_845369_war();
 }
+
+void vf610_cpu_lowlevel_init(void)
+{
+	arm_cpu_lowlevel_init();
+}
diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c
index 5ab6afc..eb2adcd 100644
--- a/arch/arm/mach-imx/imx.c
+++ b/arch/arm/mach-imx/imx.c
@@ -63,6 +63,8 @@ static int imx_soc_from_dt(void)
 		return IMX_CPU_IMX6;
 	if (of_machine_is_compatible("fsl,imx6qp"))
 		return IMX_CPU_IMX6;
+	if (of_machine_is_compatible("fsl,vf610"))
+		return IMX_CPU_VF610;
 
 	return 0;
 }
@@ -99,6 +101,8 @@ static int imx_init(void)
 		ret = imx53_init();
 	else if (cpu_is_mx6())
 		ret = imx6_init();
+	else if (cpu_is_vf610())
+		ret = 0;
 	else
 		return -EINVAL;
 
diff --git a/arch/arm/mach-imx/include/mach/generic.h b/arch/arm/mach-imx/include/mach/generic.h
index 7c275df..3419450 100644
--- a/arch/arm/mach-imx/include/mach/generic.h
+++ b/arch/arm/mach-imx/include/mach/generic.h
@@ -45,6 +45,7 @@ int imx6_devices_init(void);
 
 void imx5_cpu_lowlevel_init(void);
 void imx6_cpu_lowlevel_init(void);
+void vf610_cpu_lowlevel_init(void);
 
 /* There's a off-by-one betweem the gpio bank number and the gpiochip */
 /* range e.g. GPIO_1_5 is gpio 5 under linux */
@@ -173,6 +174,18 @@ extern unsigned int __imx_cpu_type;
 # define cpu_is_mx6()		(0)
 #endif
 
+#ifdef CONFIG_ARCH_VF610
+# ifdef imx_cpu_type
+#  undef imx_cpu_type
+#  define imx_cpu_type __imx_cpu_type
+# else
+#  define imx_cpu_type IMX_CPU_VF610
+# endif
+# define cpu_is_vf610()		(imx_cpu_type == IMX_CPU_VF610)
+#else
+# define cpu_is_vf610()		(0)
+#endif
+
 #define cpu_is_mx23()	(0)
 #define cpu_is_mx28()	(0)
 
diff --git a/arch/arm/mach-imx/include/mach/imx_cpu_types.h b/arch/arm/mach-imx/include/mach/imx_cpu_types.h
index 8472488..50be0b6 100644
--- a/arch/arm/mach-imx/include/mach/imx_cpu_types.h
+++ b/arch/arm/mach-imx/include/mach/imx_cpu_types.h
@@ -11,5 +11,6 @@
 #define IMX_CPU_IMX51	51
 #define IMX_CPU_IMX53	53
 #define IMX_CPU_IMX6	6
+#define IMX_CPU_VF610	610
 
 #endif /* __MACH_IMX_CPU_TYPES_H */
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* [PATCH v2 00/28] Vybrid support in Barebox
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Hi everyone,

It took me a bit more than a month, but I finally put together a
second version (for v1 see [1]) of the Vybrid support patchset.

Some highlights of this version:

     - Various code/commit arrangement feedback for v1 is addressed
     - Added commit to move all of the i.MX clock code to drivers/clk
       (Sascha, we'd probably have to coordinate with your i.MX6ul
       patches on this one)
     - I2C commit split in two
     - clock tree is reconciled with Linux code, since having a custom
       version of it proved to be difficult to compare agains Linux's
       implementation
     - GPIO driver (tested on a custom Vybrid board)
     - FEC support (tested on a custom Vybrid board)

Any feedback is, as always, very much appreciated.

Thank you,
Andrey Smirnov

[1] http://lists.infradead.org/pipermail/barebox/2016-October/028225.html

Andrey Smirnov (28):
  i.MX: Add primitive functions for VF610 family
  i.MX: Add register definitions for VF610 SoC
  i.MX: Add DEBUG_LL hooks for VF610
  i.MX: scripts: Add "vf610" soc to imx-image
  i.MX: Add support for VF610 Tower board
  pinctrl: Add provisions to control GPIO pin direction
  i.MX: Add pinctrl driver for VF610
  clk: Port clock dependency resolution code
  clk: Port of_clk_set_defaults()
  i.MX: Move clk code from 'mach-imx' to 'drivers'
  i.MX: clk: Port imx_clk_gate2_cgr()
  i.MX: clk: Add IMX_PLLV3_USB_VF610 support
  i.MX: clk: Port imx_check_clocks()
  i.MX: clk: Port imx_clk_mux_flags from Linux
  i.MX: Add VF610 clock tree initialization code
  vf610: Give enet_osc explicit "enet_ext" name
  i.MX: Add 'lpuart' serial driver
  i.MX: i2c: Use read/write adapter functions
  i.MX: i2c: Add Vybrid support
  i.MX: esdhc: Do not rely on CPU type for quirks
  i.MX: esdhc: Request "per" clock explicitly
  i.MX: Kconfig: Enable OCOTP on Vybrid
  i.MX: ocotp: Remove unused #define
  i.MX: ocotp: Account for shadow memory gaps
  i.MX: ocotp: Add Vybrid support
  i.MX: fec: Enable all clocks specified for FEC
  i.MX: fec: Add support for Vybrid variant
  gpio: Add GPIO driver for Vybrid

 arch/arm/boards/Makefile                           |   1 +
 arch/arm/boards/freescale-vf610-twr/Makefile       |   3 +
 .../flash-header-vf610-twr.imxcfg                  | 278 +++++++++++
 arch/arm/boards/freescale-vf610-twr/lowlevel.c     |  45 ++
 arch/arm/dts/Makefile                              |   1 +
 arch/arm/dts/vf610-twr.dts                         |  18 +
 arch/arm/mach-imx/Kconfig                          |  16 +-
 arch/arm/mach-imx/Makefile                         |  23 +-
 arch/arm/mach-imx/clk-gate-exclusive.c             | 103 ----
 arch/arm/mach-imx/clk-gate2.c                      | 145 ------
 arch/arm/mach-imx/clk-imx1.c                       | 121 -----
 arch/arm/mach-imx/clk-imx21.c                      | 196 --------
 arch/arm/mach-imx/clk-imx25.c                      | 200 --------
 arch/arm/mach-imx/clk-imx27.c                      | 270 ----------
 arch/arm/mach-imx/clk-imx31.c                      | 146 ------
 arch/arm/mach-imx/clk-imx35.c                      | 219 ---------
 arch/arm/mach-imx/clk-imx5.c                       | 533 --------------------
 arch/arm/mach-imx/clk-imx6.c                       | 541 ---------------------
 arch/arm/mach-imx/clk-imx6sx.c                     | 483 ------------------
 arch/arm/mach-imx/clk-pfd.c                        | 148 ------
 arch/arm/mach-imx/clk-pllv1.c                      |  95 ----
 arch/arm/mach-imx/clk-pllv2.c                      | 230 ---------
 arch/arm/mach-imx/clk-pllv3.c                      | 326 -------------
 arch/arm/mach-imx/clk.h                            | 104 ----
 arch/arm/mach-imx/cpu_init.c                       |   5 +
 arch/arm/mach-imx/imx.c                            |   4 +
 arch/arm/mach-imx/include/mach/clock-vf610.h       | 171 +++++++
 arch/arm/mach-imx/include/mach/debug_ll.h          |  27 +-
 arch/arm/mach-imx/include/mach/generic.h           |  13 +
 arch/arm/mach-imx/include/mach/imx_cpu_types.h     |   1 +
 arch/arm/mach-imx/include/mach/iomux-vf610.h       | 226 +++++++++
 arch/arm/mach-imx/include/mach/vf610-regs.h        | 110 +++++
 arch/arm/mach-imx/ocotp.c                          |  51 +-
 common/Kconfig                                     |  10 +-
 drivers/clk/Makefile                               |   3 +-
 drivers/clk/clk-conf.c                             | 144 ++++++
 drivers/clk/clk.c                                  |  91 +++-
 drivers/clk/imx/Makefile                           |  21 +
 drivers/clk/imx/clk-gate-exclusive.c               | 103 ++++
 drivers/clk/imx/clk-gate2.c                        | 147 ++++++
 drivers/clk/imx/clk-imx1.c                         | 121 +++++
 drivers/clk/imx/clk-imx21.c                        | 196 ++++++++
 drivers/clk/imx/clk-imx25.c                        | 200 ++++++++
 drivers/clk/imx/clk-imx27.c                        | 270 ++++++++++
 drivers/clk/imx/clk-imx31.c                        | 146 ++++++
 drivers/clk/imx/clk-imx35.c                        | 219 +++++++++
 drivers/clk/imx/clk-imx5.c                         | 533 ++++++++++++++++++++
 drivers/clk/imx/clk-imx6.c                         | 541 +++++++++++++++++++++
 drivers/clk/imx/clk-imx6sx.c                       | 483 ++++++++++++++++++
 drivers/clk/imx/clk-pfd.c                          | 148 ++++++
 drivers/clk/imx/clk-pllv1.c                        |  95 ++++
 drivers/clk/imx/clk-pllv2.c                        | 230 +++++++++
 drivers/clk/imx/clk-pllv3.c                        | 329 +++++++++++++
 drivers/clk/imx/clk-vf610.c                        | 443 +++++++++++++++++
 drivers/clk/imx/clk.c                              |  21 +
 drivers/clk/imx/clk.h                              | 123 +++++
 drivers/gpio/Kconfig                               |   3 +
 drivers/gpio/Makefile                              |   1 +
 drivers/gpio/gpio-vf610.c                          | 181 +++++++
 drivers/i2c/busses/i2c-imx.c                       | 225 ++++++---
 drivers/mci/imx-esdhc.c                            | 123 ++++-
 drivers/net/fec_imx.c                              |  74 ++-
 drivers/net/fec_imx.h                              |  10 +-
 drivers/pinctrl/Kconfig                            |   5 +
 drivers/pinctrl/Makefile                           |   1 +
 drivers/pinctrl/pinctrl-vf610.c                    | 167 +++++++
 drivers/pinctrl/pinctrl.c                          |  45 ++
 drivers/serial/Kconfig                             |   5 +
 drivers/serial/Makefile                            |   1 +
 drivers/serial/serial_lpuart.c                     | 217 +++++++++
 images/Makefile.imx                                |   5 +
 include/linux/clk/clk-conf.h                       |  14 +
 include/pinctrl.h                                  |  21 +
 include/serial/lpuart.h                            | 281 +++++++++++
 scripts/imx/imx.c                                  |   1 +
 75 files changed, 6870 insertions(+), 3980 deletions(-)
 create mode 100644 arch/arm/boards/freescale-vf610-twr/Makefile
 create mode 100644 arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
 create mode 100644 arch/arm/boards/freescale-vf610-twr/lowlevel.c
 create mode 100644 arch/arm/dts/vf610-twr.dts
 delete mode 100644 arch/arm/mach-imx/clk-gate-exclusive.c
 delete mode 100644 arch/arm/mach-imx/clk-gate2.c
 delete mode 100644 arch/arm/mach-imx/clk-imx1.c
 delete mode 100644 arch/arm/mach-imx/clk-imx21.c
 delete mode 100644 arch/arm/mach-imx/clk-imx25.c
 delete mode 100644 arch/arm/mach-imx/clk-imx27.c
 delete mode 100644 arch/arm/mach-imx/clk-imx31.c
 delete mode 100644 arch/arm/mach-imx/clk-imx35.c
 delete mode 100644 arch/arm/mach-imx/clk-imx5.c
 delete mode 100644 arch/arm/mach-imx/clk-imx6.c
 delete mode 100644 arch/arm/mach-imx/clk-imx6sx.c
 delete mode 100644 arch/arm/mach-imx/clk-pfd.c
 delete mode 100644 arch/arm/mach-imx/clk-pllv1.c
 delete mode 100644 arch/arm/mach-imx/clk-pllv2.c
 delete mode 100644 arch/arm/mach-imx/clk-pllv3.c
 delete mode 100644 arch/arm/mach-imx/clk.h
 create mode 100644 arch/arm/mach-imx/include/mach/clock-vf610.h
 create mode 100644 arch/arm/mach-imx/include/mach/iomux-vf610.h
 create mode 100644 arch/arm/mach-imx/include/mach/vf610-regs.h
 create mode 100644 drivers/clk/clk-conf.c
 create mode 100644 drivers/clk/imx/Makefile
 create mode 100644 drivers/clk/imx/clk-gate-exclusive.c
 create mode 100644 drivers/clk/imx/clk-gate2.c
 create mode 100644 drivers/clk/imx/clk-imx1.c
 create mode 100644 drivers/clk/imx/clk-imx21.c
 create mode 100644 drivers/clk/imx/clk-imx25.c
 create mode 100644 drivers/clk/imx/clk-imx27.c
 create mode 100644 drivers/clk/imx/clk-imx31.c
 create mode 100644 drivers/clk/imx/clk-imx35.c
 create mode 100644 drivers/clk/imx/clk-imx5.c
 create mode 100644 drivers/clk/imx/clk-imx6.c
 create mode 100644 drivers/clk/imx/clk-imx6sx.c
 create mode 100644 drivers/clk/imx/clk-pfd.c
 create mode 100644 drivers/clk/imx/clk-pllv1.c
 create mode 100644 drivers/clk/imx/clk-pllv2.c
 create mode 100644 drivers/clk/imx/clk-pllv3.c
 create mode 100644 drivers/clk/imx/clk-vf610.c
 create mode 100644 drivers/clk/imx/clk.c
 create mode 100644 drivers/clk/imx/clk.h
 create mode 100644 drivers/gpio/gpio-vf610.c
 create mode 100644 drivers/pinctrl/pinctrl-vf610.c
 create mode 100644 drivers/serial/serial_lpuart.c
 create mode 100644 include/linux/clk/clk-conf.h
 create mode 100644 include/serial/lpuart.h

-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply

* [PATCH v2 07/28] i.MX: Add pinctrl driver for VF610
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/pinctrl/Kconfig         |   5 ++
 drivers/pinctrl/Makefile        |   1 +
 drivers/pinctrl/pinctrl-vf610.c | 167 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 173 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-vf610.c

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 5c69928..12fff4f 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -77,4 +77,9 @@ config PINCTRL_TEGRA_XUSB
 
 source drivers/pinctrl/mvebu/Kconfig
 
+config PINCTRL_VF610
+	bool
+	default y if ARCH_VF610
+	help
+	  Pinmux controller found on Vybrid VF610 family of SoCs
 endif
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index af9b30d..9450dbb 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -9,5 +9,6 @@ obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
 obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o
 obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o
 obj-$(CONFIG_PINCTRL_TEGRA_XUSB) += pinctrl-tegra-xusb.o
+obj-$(CONFIG_PINCTRL_VF610) += pinctrl-vf610.o
 
 obj-$(CONFIG_ARCH_MVEBU) += mvebu/
diff --git a/drivers/pinctrl/pinctrl-vf610.c b/drivers/pinctrl/pinctrl-vf610.c
new file mode 100644
index 0000000..b479bf2
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-vf610.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2016 Zodiac Inflight Innovation
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <of.h>
+#include <pinctrl.h>
+#include <malloc.h>
+#include <gpio.h>
+
+enum {
+	PINCTRL_VF610_MUX_LINE_SIZE = 20,
+	PINCTRL_VF610_MUX_SHIFT = 20,
+
+	PINCTRL_VF610_IBE = 1 << 0,
+	PINCTRL_VF610_OBE = 1 << 1,
+	PINCTRL_VF610_xBE = 0b11,
+};
+
+struct pinctrl_vf610 {
+	void __iomem *base;
+	struct pinctrl_device pinctrl;
+};
+
+static int pinctrl_vf610_set_state(struct pinctrl_device *pdev,
+				   struct device_node *np)
+{
+	const __be32 *list;
+	int npins, size, i;
+
+	struct pinctrl_vf610 *iomux =
+		container_of(pdev, struct pinctrl_vf610, pinctrl);
+
+	list = of_get_property(np, "fsl,pins", &size);
+	if (!list)
+		return -EINVAL;
+
+	if (!size || size % PINCTRL_VF610_MUX_LINE_SIZE) {
+		dev_err(pdev->dev, "Invalid fsl,pins property in %s\n",
+			np->full_name);
+		return -EINVAL;
+	}
+
+	npins = size / PINCTRL_VF610_MUX_LINE_SIZE;
+
+	for (i = 0; i < npins; i++) {
+		u32 mux_reg   = be32_to_cpu(*list++);
+		u32 input_reg = be32_to_cpu(*list++);
+		u32 mux_val   = be32_to_cpu(*list++);
+		u32 input_val = be32_to_cpu(*list++);
+		u32 conf_val  = be32_to_cpu(*list++);
+
+		writel(mux_val << PINCTRL_VF610_MUX_SHIFT | conf_val,
+		       iomux->base + mux_reg);
+
+		if (input_reg)
+			writel(input_val, iomux->base + input_reg);
+	}
+
+	return 0;
+}
+
+static int pinctrl_vf610_set_direction(struct pinctrl_device *pdev,
+				       unsigned int pin, bool input)
+{
+	u32 pad_cr;
+	const u32 off = pin * sizeof(u32);
+	struct pinctrl_vf610 *iomux =
+		container_of(pdev, struct pinctrl_vf610, pinctrl);
+
+	pad_cr = readl(iomux->base + off);
+
+	if (input) {
+		pad_cr |= PINCTRL_VF610_IBE;
+		pad_cr &= ~PINCTRL_VF610_OBE;
+	} else {
+		pad_cr &= ~PINCTRL_VF610_IBE;
+		pad_cr |= PINCTRL_VF610_OBE;
+	}
+
+	writel(pad_cr, iomux->base + off);
+
+	return 0;
+}
+
+static int pinctrl_vf610_get_direction(struct pinctrl_device *pdev,
+				       unsigned int pin)
+{
+	const u32 off = pin * sizeof(u32);
+	struct pinctrl_vf610 *iomux =
+		container_of(pdev, struct pinctrl_vf610, pinctrl);
+
+	const u32 pad_cr = readl(iomux->base + off);
+
+	switch (pad_cr & PINCTRL_VF610_xBE) {
+	case PINCTRL_VF610_IBE:
+		return GPIOF_DIR_IN;
+	case PINCTRL_VF610_OBE:
+		return GPIOF_DIR_OUT;
+	default:
+		return -EINVAL;
+	}
+}
+
+static struct pinctrl_ops pinctrl_vf610_ops = {
+	.set_state = pinctrl_vf610_set_state,
+	.set_direction = pinctrl_vf610_set_direction,
+	.get_direction = pinctrl_vf610_get_direction,
+};
+
+static int pinctrl_vf610_probe(struct device_d *dev)
+{
+	int ret;
+	struct resource *io;
+	struct pinctrl_vf610 *iomux;
+
+	iomux = xzalloc(sizeof(*iomux));
+
+	io = dev_request_mem_resource(dev, 0);
+	if (IS_ERR(io))
+		return PTR_ERR(io);
+
+	iomux->base = IOMEM(io->start);
+	iomux->pinctrl.dev = dev;
+	iomux->pinctrl.ops = &pinctrl_vf610_ops;
+	iomux->pinctrl.base = 0;
+	iomux->pinctrl.npins = ARCH_NR_GPIOS;
+
+	ret = pinctrl_register(&iomux->pinctrl);
+	if (ret)
+		free(iomux);
+
+	return ret;
+}
+
+static __maybe_unused struct of_device_id pinctrl_vf610_dt_ids[] = {
+	{ .compatible = "fsl,vf610-iomuxc", },
+	{ /* sentinel */ }
+};
+
+static struct driver_d pinctrl_vf610_driver = {
+	.name		= "vf610-pinctrl",
+	.probe		= pinctrl_vf610_probe,
+	.of_compatible	= DRV_OF_COMPAT(pinctrl_vf610_dt_ids),
+};
+
+static int pinctrl_vf610_init(void)
+{
+	return platform_driver_register(&pinctrl_vf610_driver);
+}
+postcore_initcall(pinctrl_vf610_init);
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply related

* Re: [OSSTEST PATCH v6 1/3] ts-openstack-deploy: Deploy OpenStack on a host with devstack
From: Ian Jackson @ 2016-11-09 16:14 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel
In-Reply-To: <20161031175233.32320-2-anthony.perard@citrix.com>

Anthony PERARD writes ("[OSSTEST PATCH v6 1/3] ts-openstack-deploy: Deploy OpenStack on a host with devstack"):
> This script installs any necessary packages and clones all of the OpenStack
> trees which are used by devstack to deploy OpenStack.

Thanks for this contribution.  I have no knowledge of OpenStack so I
can't really know whether what you are doing here is right, but it
looks basically OK to me.


I have some minor comments.  The most annoying one will be that I
would like you to file bugs in appropriate upstream bug trackers
(OpenStack or Debian), for each of the the workarounds.  Sorry...



> +sub packages () {
> +  # Install open-iscsi ahead of devstack ...
> +  target_install_packages($ho, qw(git sudo open-iscsi));

The indentation is a bit odd.  I won't insist you fix it, but usual
indent in osstest is 4 spaces.

> +  # ... and start open-iscsi to have /etc/iscsi/initiatorname.iscsi
> +  # generated. This is done on install on Ubuntu.
> +  target_cmd_root($ho, 'service open-iscsi start');

This looks like it is a workaround.  Can you please
 1. file a bug against Debian
 2. quote the bug number in your code
 3. make the workaround conditional on the suite

> +sub checkout () {
> +  prepbuilddirs();
> +  build_clone($ho, 'cinder', $builddir, 'cinder');
> +  build_clone($ho, 'devstack', $builddir, 'devstack');
> +  build_clone($ho, 'glance', $builddir, 'glance');
> +  build_clone($ho, 'keystone', $builddir, 'keystone');
> +  build_clone($ho, 'nova', $builddir, 'nova');
> +  build_clone($ho, 'requirements', $builddir, 'requirements');
> +  build_clone($ho, 'tempest', $builddir, 'tempest');

This could profitably be reformatted with extra whitespace so that the
columns line up.  (Again I won't insist on this.)

> +LOGFILE=\$DEST/logs/stack.sh.log
> +# stackrc set this but don't take \$DEST into account

ITYM "sets this but doesn't take".

> +  # stackrc does not take $DEST from local.conf into account, so fix it here
> +  target_editfile($ho, "$builddir/devstack/stackrc", sub {

This is a workround for an upstream bug ?  Is there a corresponding
upstream bug report ?  Should there be ?

In osstest I like to reduce, where possible, unconditional workarounds
for bugs in the software under test.  In general there should be an
upstream bug report, referred to in the osstest code.  Ideally there
would be a way to automatically disable the workaround eventually,
although that's probably too difficult here.

> +      while (<EI>) {
> +        if (m/^DEST=\/opt\/stack$/) {
> +          s/DEST=\/opt\/stack/DEST=$builddir/;

Using a regexp delimiter other than // would make this much clearer.

  +        if (m{^DEST=/opt/stack$}) {
  +        if (m#^DEST=/opt/stack$}) {
  +          s{DEST=/opt/stack}{DEST=$builddir};
  +          s#DEST=/opt/stack#DEST=$builddir#;

For example.  Take your pick.  I see later you used % % which is also
OK, although it is not the most idiomatic Perl (since the human reader
will tend to see % as a reference to a hash).

> +  # libvirt is already installed, but not as a package, so avoid installation of
> +  # the libvirt package with devstack
> +  target_editfile($ho, "$builddir/devstack/files/debs/nova", sub {
> +      while (<EI>) {
> +        next if m/.*libvirt.*/;
> +        print EO or die $!;
> +      }
> +  });
> +  target_editfile($ho, "$builddir/devstack/lib/nova_plugins/functions-libvirt", sub {
> +      while (<EI>) {
> +        next if m/install_package.*libvirt.*/;
> +        print EO or die $!;
> +      }
> +  });

These look like they ought to come with an upstream wishlist bug
asking for a front-door way to achieve this.

> +  # devstack blindly assume that systemd is used if systemctl is present
> +  target_editfile($ho, "$builddir/devstack/functions-common", sub {
> +      while (<EI>) {
> +        if (m%\[ -x /bin/systemctl%) {
> +          s%\[ -x /bin/systemctl \]%false%
> +        }
> +        print EO or die $!;
> +      }
> +  });

Again, an upstream bug.

> +  # OpenStack needs access to libvirt from a user.
> +  target_cmd_root($ho, <<END);
> +    if ! getent group libvirt >/dev/null; then
> +      groupadd libvirt

You should probably use "addgroup --system".  That is idempotent, so
you do not need the test.

> +    # For unknown reason, restart fail when done by devstack
> +    # so stop the service here, and devstack will start it.

Again, upstream bug.

> +  # devstack is going to setup the host, install some dependency.
> +  target_putfilecontents_root_stash($ho, 100, <<END,"/etc/sudoers.d/devstack");

How ... exciting.  This is rather mad but I don't think it is harmful
in the context of osstest.  So, fine.

> +  target_putfilecontents_root_stash($ho, 60, tgt_init(), "/etc/init.d/tgt");
> +  target_cmd_root($ho, <<END);
> +    chmod +x /etc/init.d/tgt
> +END
> +}

You may find it better to combine some of these target_cmd_root
stanzas.  That would reduce the overall amount of clutter in the perl
code.

> +# This is missing from Debian but required by devstack
> +# Got it from https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=577925
> +sub tgt_init () {

This should be conditional on the suite.  The bug seems to be fixed in
2014 and is allegedly fixed in stable (jessie).  So the workaround is
no longer necessary ?

Ian.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply

* Re: [PATCH] megaraid_sas: fix macro MEGASAS_IS_LOGICAL to avoid regression caused by commit 1e793f6fc0db920400574211c48f9157a37e3945
From: Jens Axboe @ 2016-11-09 16:14 UTC (permalink / raw)
  To: Sumit Saxena, linux-scsi
  Cc: martin.petersen, thenzl, jejb, kashyap.desai,
	shivasharan.srikanteshwara, stable
In-Reply-To: <1478689182-10854-1-git-send-email-sumit.saxena@broadcom.com>

On 11/09/2016 03:59 AM, Sumit Saxena wrote:
> This patch will fix regression caused by below commit-
> 1e793f6 scsi: megaraid_sas: Fix data integrity failure for JBOD (passthrough) devices
>
> The problem was MEGASAS_IS_LOGICAL macro does not have braces and because of above commit
> using this macro was exposing lot of non-existing SCSI devices(all SCSI commands to channels-1,2,3 was
> returned as SUCCESS-DID_OK by driver).
>
> Fixes: 1e793f6fc0db920400574211c48f9157a37e3945
> Reported-by: Jens Axboe <axboe@kernel.dk>
> CC: stable@vger.kernel.org
> Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com>
> Signed-off-by: Sumit Saxena <sumit.saxena@broadcom.com>
> Tested-by: Sumit Saxena <sumit.saxena@broadcom.com>

Tested-by: Jens Axboe <axboe@fb.com>

-- 
Jens Axboe


^ permalink raw reply

* [BACKPORT PATCH 3.10..3.16 2/2] KVM: MIPS: Precalculate MMIO load resume PC
From: James Hogan @ 2016-11-09 16:13 UTC (permalink / raw)
  To: stable
  Cc: Paolo Bonzini, Radim Krčmář, Ralf Baechle,
	linux-mips, kvm, James Hogan
In-Reply-To: <2e791b20c24570339d15118a55e174f5b2d63ac1.1478707766.git-series.james.hogan@imgtec.com>

commit e1e575f6b026734be3b1f075e780e91ab08ca541 upstream.

The advancing of the PC when completing an MMIO load is done before
re-entering the guest, i.e. before restoring the guest ASID. However if
the load is in a branch delay slot it may need to access guest code to
read the prior branch instruction. This isn't safe in TLB mapped code at
the moment, nor in the future when we'll access unmapped guest segments
using direct user accessors too, as it could read the branch from host
user memory instead.

Therefore calculate the resume PC in advance while we're still in the
right context and save it in the new vcpu->arch.io_pc (replacing the no
longer needed vcpu->arch.pending_load_cause), and restore it on MMIO
completion.

Fixes: e685c689f3a8 ("KVM/MIPS32: Privileged instruction/target branch emulation.")
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Radim Krčmář <rkrcmar@redhat.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
Cc: kvm@vger.kernel.org
Cc: <stable@vger.kernel.org> # 3.10.x-3.16.x: 5f508c43a764: MIPS: KVM: Fix unused variable build warning
Cc: <stable@vger.kernel.org> # 3.10.x-3.16.x
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[james.hogan@imgtec.com: Backport to 3.10..3.16]
Signed-off-by: James Hogan <james.hogan@imgtec.com>
---
 arch/mips/include/asm/kvm_host.h |  7 ++++---
 arch/mips/kvm/kvm_mips_emul.c    | 25 +++++++++++++++----------
 2 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h
index 5bddbc63fc3b..f8cdc274173a 100644
--- a/arch/mips/include/asm/kvm_host.h
+++ b/arch/mips/include/asm/kvm_host.h
@@ -403,7 +403,10 @@ struct kvm_vcpu_arch {
 	/* Host KSEG0 address of the EI/DI offset */
 	void *kseg0_commpage;
 
-	u32 io_gpr;		/* GPR used as IO source/target */
+	/* Resume PC after MMIO completion */
+	unsigned long io_pc;
+	/* GPR used as IO source/target */
+	u32 io_gpr;
 
 	struct hrtimer comparecount_timer;
 	/* Count timer control KVM register */
@@ -425,8 +428,6 @@ struct kvm_vcpu_arch {
 	/* Bitmask of pending exceptions to be cleared */
 	unsigned long pending_exceptions_clr;
 
-	unsigned long pending_load_cause;
-
 	/* Save/Restore the entryhi register when are are preempted/scheduled back in */
 	unsigned long preempt_entryhi;
 
diff --git a/arch/mips/kvm/kvm_mips_emul.c b/arch/mips/kvm/kvm_mips_emul.c
index a32e838d9aeb..4feffc82f39a 100644
--- a/arch/mips/kvm/kvm_mips_emul.c
+++ b/arch/mips/kvm/kvm_mips_emul.c
@@ -1283,6 +1283,7 @@ kvm_mips_emulate_load(uint32_t inst, uint32_t cause,
 		      struct kvm_run *run, struct kvm_vcpu *vcpu)
 {
 	enum emulation_result er = EMULATE_DO_MMIO;
+	unsigned long curr_pc;
 	int32_t op, base, rt, offset;
 	uint32_t bytes;
 
@@ -1291,7 +1292,18 @@ kvm_mips_emulate_load(uint32_t inst, uint32_t cause,
 	offset = inst & 0xffff;
 	op = (inst >> 26) & 0x3f;
 
-	vcpu->arch.pending_load_cause = cause;
+	/*
+	 * Find the resume PC now while we have safe and easy access to the
+	 * prior branch instruction, and save it for
+	 * kvm_mips_complete_mmio_load() to restore later.
+	 */
+	curr_pc = vcpu->arch.pc;
+	er = update_pc(vcpu, cause);
+	if (er == EMULATE_FAIL)
+		return er;
+	vcpu->arch.io_pc = vcpu->arch.pc;
+	vcpu->arch.pc = curr_pc;
+
 	vcpu->arch.io_gpr = rt;
 
 	switch (op) {
@@ -2122,9 +2134,8 @@ kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		goto done;
 	}
 
-	er = update_pc(vcpu, vcpu->arch.pending_load_cause);
-	if (er == EMULATE_FAIL)
-		return er;
+	/* Restore saved resume PC */
+	vcpu->arch.pc = vcpu->arch.io_pc;
 
 	switch (run->mmio.len) {
 	case 4:
@@ -2146,12 +2157,6 @@ kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		break;
 	}
 
-	if (vcpu->arch.pending_load_cause & CAUSEF_BD)
-		kvm_debug
-		    ("[%#lx] Completing %d byte BD Load to gpr %d (0x%08lx) type %d\n",
-		     vcpu->arch.pc, run->mmio.len, vcpu->arch.io_gpr, *gpr,
-		     vcpu->mmio_needed);
-
 done:
 	return er;
 }
-- 
git-series 0.8.10

^ permalink raw reply related

* Re: [PATCH 2/4] mfd: palmas: Reset the POWERHOLD mux during power off
From: Lee Jones @ 2016-11-09 16:14 UTC (permalink / raw)
  To: Keerthy
  Cc: tony-4v6yS6AI5VpBDgjK7y7TUQ, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-gpio-u79uwXL29TY76Z2rM5mHXA, nm-l0cyMroinI0,
	t-kristo-l0cyMroinI0
In-Reply-To: <1477559414-12520-3-git-send-email-j-keerthy-l0cyMroinI0@public.gmane.org>

On Thu, 27 Oct 2016, Keerthy wrote:

> POWERHOLD signal has higher priority  over the DEV_ON bit.
> So power off will not happen if the POWERHOLD is held high.
> Hence reset the MUX to GPIO_7 mode to release the POWERHOLD
> and the DEV_ON bit to take effect to power off the PMIC.
> 
> PMIC Power off happens in dire situations like thermal shutdown
> so irrespective of the POWERHOLD setting go ahead and turn off
> the powerhold.  Currently poweroff is broken on boards that have
> powerhold enabled. This fixes poweroff on those boards.
> 
> Signed-off-by: Keerthy <j-keerthy-l0cyMroinI0@public.gmane.org>
> ---
>  drivers/mfd/palmas.c | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
> 
> diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c
> index 8f8bacb..8fbc5e0 100644
> --- a/drivers/mfd/palmas.c
> +++ b/drivers/mfd/palmas.c
> @@ -430,10 +430,28 @@ static void palmas_power_off(void)
>  {
>  	unsigned int addr;
>  	int ret, slave;
> +	struct device_node *node;
> +	bool override_powerhold;
>  
>  	if (!palmas_dev)

Can this happen?

>  		return;
>  
> +	node = palmas_dev->dev->of_node;

Just do:

struct device_node *np = palmas_dev->dev->of_node;

> +	override_powerhold = of_property_read_bool(node,
> +					"ti,palmas-override-powerhold");

Break the line after the '=' instead.

> +	if (override_powerhold) {

if (of_property_read_bool(node,	"ti,palmas-override-powerhold"))

Then remove 'override_powerhold'.

> +		addr = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE,
> +					  PALMAS_PRIMARY_SECONDARY_PAD2);
> +		slave = PALMAS_BASE_TO_SLAVE(PALMAS_PU_PD_OD_BASE);
> +
> +		ret = regmap_update_bits(palmas_dev->regmap[slave], addr,
> +					 PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_7_MASK, 0);
> +		if (ret)
> +			pr_err("%s: Unable to write PALMAS_PRIMARY_SECONDARY_PAD2 %d\n",
> +			       __func__, ret);

Don't use __func__ in live code.

And use dev_err();


> +	}
> +
>  	slave = PALMAS_BASE_TO_SLAVE(PALMAS_PMU_CONTROL_BASE);
>  	addr = PALMAS_BASE_TO_REG(PALMAS_PMU_CONTROL_BASE, PALMAS_DEV_CTRL);
>  

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [BACKPORT PATCH 3.10..3.16 1/2] MIPS: KVM: Fix unused variable build warning
From: James Hogan @ 2016-11-09 16:13 UTC (permalink / raw)
  To: stable
  Cc: Paolo Bonzini, Radim Krčmář, Ralf Baechle,
	linux-mips, kvm, James Hogan

From: Nicholas Mc Guire <hofrat@osadl.org>

commit 5f508c43a7648baa892528922402f1e13f258bd4 upstream.

As kvm_mips_complete_mmio_load() did not yet modify PC at this point
as James Hogans <james.hogan@imgtec.com> explained the curr_pc variable
and the comments along with it can be dropped.

Signed-off-by: Nicholas Mc Guire <hofrat@osadl.org>
Link: http://lkml.org/lkml/2015/5/8/422
Cc: Gleb Natapov <gleb@kernel.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: James Hogan <james.hogan@imgtec.com>
Cc: kvm@vger.kernel.org
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/9993/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
[james.hogan@imgtec.com: Backport to 3.10..3.16]
Signed-off-by: James Hogan <james.hogan@imgtec.com>
---
 arch/mips/kvm/kvm_mips_emul.c | 6 ------
 1 file changed, 0 insertions(+), 6 deletions(-)

diff --git a/arch/mips/kvm/kvm_mips_emul.c b/arch/mips/kvm/kvm_mips_emul.c
index 1983678883c9..a32e838d9aeb 100644
--- a/arch/mips/kvm/kvm_mips_emul.c
+++ b/arch/mips/kvm/kvm_mips_emul.c
@@ -2115,7 +2115,6 @@ kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
 	unsigned long *gpr = &vcpu->arch.gprs[vcpu->arch.io_gpr];
 	enum emulation_result er = EMULATE_DONE;
-	unsigned long curr_pc;
 
 	if (run->mmio.len > sizeof(*gpr)) {
 		printk("Bad MMIO length: %d", run->mmio.len);
@@ -2123,11 +2122,6 @@ kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		goto done;
 	}
 
-	/*
-	 * Update PC and hold onto current PC in case there is
-	 * an error and we want to rollback the PC
-	 */
-	curr_pc = vcpu->arch.pc;
 	er = update_pc(vcpu, vcpu->arch.pending_load_cause);
 	if (er == EMULATE_FAIL)
 		return er;
-- 
git-series 0.8.10

^ permalink raw reply related

* [BACKPORT PATCH 3.10..3.16 2/2] KVM: MIPS: Precalculate MMIO load resume PC
From: James Hogan @ 2016-11-09 16:13 UTC (permalink / raw)
  To: stable
  Cc: Paolo Bonzini, Radim Krčmář, Ralf Baechle,
	linux-mips, kvm, James Hogan
In-Reply-To: <2e791b20c24570339d15118a55e174f5b2d63ac1.1478707766.git-series.james.hogan@imgtec.com>

commit e1e575f6b026734be3b1f075e780e91ab08ca541 upstream.

The advancing of the PC when completing an MMIO load is done before
re-entering the guest, i.e. before restoring the guest ASID. However if
the load is in a branch delay slot it may need to access guest code to
read the prior branch instruction. This isn't safe in TLB mapped code at
the moment, nor in the future when we'll access unmapped guest segments
using direct user accessors too, as it could read the branch from host
user memory instead.

Therefore calculate the resume PC in advance while we're still in the
right context and save it in the new vcpu->arch.io_pc (replacing the no
longer needed vcpu->arch.pending_load_cause), and restore it on MMIO
completion.

Fixes: e685c689f3a8 ("KVM/MIPS32: Privileged instruction/target branch emulation.")
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Radim Krčmář <rkrcmar@redhat.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
Cc: kvm@vger.kernel.org
Cc: <stable@vger.kernel.org> # 3.10.x-3.16.x: 5f508c43a764: MIPS: KVM: Fix unused variable build warning
Cc: <stable@vger.kernel.org> # 3.10.x-3.16.x
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[james.hogan@imgtec.com: Backport to 3.10..3.16]
Signed-off-by: James Hogan <james.hogan@imgtec.com>
---
 arch/mips/include/asm/kvm_host.h |  7 ++++---
 arch/mips/kvm/kvm_mips_emul.c    | 25 +++++++++++++++----------
 2 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h
index 5bddbc63fc3b..f8cdc274173a 100644
--- a/arch/mips/include/asm/kvm_host.h
+++ b/arch/mips/include/asm/kvm_host.h
@@ -403,7 +403,10 @@ struct kvm_vcpu_arch {
 	/* Host KSEG0 address of the EI/DI offset */
 	void *kseg0_commpage;
 
-	u32 io_gpr;		/* GPR used as IO source/target */
+	/* Resume PC after MMIO completion */
+	unsigned long io_pc;
+	/* GPR used as IO source/target */
+	u32 io_gpr;
 
 	struct hrtimer comparecount_timer;
 	/* Count timer control KVM register */
@@ -425,8 +428,6 @@ struct kvm_vcpu_arch {
 	/* Bitmask of pending exceptions to be cleared */
 	unsigned long pending_exceptions_clr;
 
-	unsigned long pending_load_cause;
-
 	/* Save/Restore the entryhi register when are are preempted/scheduled back in */
 	unsigned long preempt_entryhi;
 
diff --git a/arch/mips/kvm/kvm_mips_emul.c b/arch/mips/kvm/kvm_mips_emul.c
index a32e838d9aeb..4feffc82f39a 100644
--- a/arch/mips/kvm/kvm_mips_emul.c
+++ b/arch/mips/kvm/kvm_mips_emul.c
@@ -1283,6 +1283,7 @@ kvm_mips_emulate_load(uint32_t inst, uint32_t cause,
 		      struct kvm_run *run, struct kvm_vcpu *vcpu)
 {
 	enum emulation_result er = EMULATE_DO_MMIO;
+	unsigned long curr_pc;
 	int32_t op, base, rt, offset;
 	uint32_t bytes;
 
@@ -1291,7 +1292,18 @@ kvm_mips_emulate_load(uint32_t inst, uint32_t cause,
 	offset = inst & 0xffff;
 	op = (inst >> 26) & 0x3f;
 
-	vcpu->arch.pending_load_cause = cause;
+	/*
+	 * Find the resume PC now while we have safe and easy access to the
+	 * prior branch instruction, and save it for
+	 * kvm_mips_complete_mmio_load() to restore later.
+	 */
+	curr_pc = vcpu->arch.pc;
+	er = update_pc(vcpu, cause);
+	if (er == EMULATE_FAIL)
+		return er;
+	vcpu->arch.io_pc = vcpu->arch.pc;
+	vcpu->arch.pc = curr_pc;
+
 	vcpu->arch.io_gpr = rt;
 
 	switch (op) {
@@ -2122,9 +2134,8 @@ kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		goto done;
 	}
 
-	er = update_pc(vcpu, vcpu->arch.pending_load_cause);
-	if (er == EMULATE_FAIL)
-		return er;
+	/* Restore saved resume PC */
+	vcpu->arch.pc = vcpu->arch.io_pc;
 
 	switch (run->mmio.len) {
 	case 4:
@@ -2146,12 +2157,6 @@ kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		break;
 	}
 
-	if (vcpu->arch.pending_load_cause & CAUSEF_BD)
-		kvm_debug
-		    ("[%#lx] Completing %d byte BD Load to gpr %d (0x%08lx) type %d\n",
-		     vcpu->arch.pc, run->mmio.len, vcpu->arch.io_gpr, *gpr,
-		     vcpu->mmio_needed);
-
 done:
 	return er;
 }
-- 
git-series 0.8.10

^ permalink raw reply related

* [BACKPORT PATCH 3.10..3.16 1/2] MIPS: KVM: Fix unused variable build warning
From: James Hogan @ 2016-11-09 16:13 UTC (permalink / raw)
  To: stable
  Cc: Paolo Bonzini, Radim Krčmář, Ralf Baechle,
	linux-mips, kvm, James Hogan

From: Nicholas Mc Guire <hofrat@osadl.org>

commit 5f508c43a7648baa892528922402f1e13f258bd4 upstream.

As kvm_mips_complete_mmio_load() did not yet modify PC at this point
as James Hogans <james.hogan@imgtec.com> explained the curr_pc variable
and the comments along with it can be dropped.

Signed-off-by: Nicholas Mc Guire <hofrat@osadl.org>
Link: http://lkml.org/lkml/2015/5/8/422
Cc: Gleb Natapov <gleb@kernel.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: James Hogan <james.hogan@imgtec.com>
Cc: kvm@vger.kernel.org
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/9993/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
[james.hogan@imgtec.com: Backport to 3.10..3.16]
Signed-off-by: James Hogan <james.hogan@imgtec.com>
---
 arch/mips/kvm/kvm_mips_emul.c | 6 ------
 1 file changed, 0 insertions(+), 6 deletions(-)

diff --git a/arch/mips/kvm/kvm_mips_emul.c b/arch/mips/kvm/kvm_mips_emul.c
index 1983678883c9..a32e838d9aeb 100644
--- a/arch/mips/kvm/kvm_mips_emul.c
+++ b/arch/mips/kvm/kvm_mips_emul.c
@@ -2115,7 +2115,6 @@ kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
 	unsigned long *gpr = &vcpu->arch.gprs[vcpu->arch.io_gpr];
 	enum emulation_result er = EMULATE_DONE;
-	unsigned long curr_pc;
 
 	if (run->mmio.len > sizeof(*gpr)) {
 		printk("Bad MMIO length: %d", run->mmio.len);
@@ -2123,11 +2122,6 @@ kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		goto done;
 	}
 
-	/*
-	 * Update PC and hold onto current PC in case there is
-	 * an error and we want to rollback the PC
-	 */
-	curr_pc = vcpu->arch.pc;
 	er = update_pc(vcpu, vcpu->arch.pending_load_cause);
 	if (er == EMULATE_FAIL)
 		return er;
-- 
git-series 0.8.10

^ permalink raw reply related

* [PATCH v4l-utils 3/3] ir-keytable: make it possible to select the rc5 streamzap variant
From: Sean Young @ 2016-11-09 16:13 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: linux-media

It was not possible to select the rc-5-sz protocol.

Signed-off-by: Sean Young <sean@mess.org>
---
 utils/keytable/keytable.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/utils/keytable/keytable.c b/utils/keytable/keytable.c
index 3922ad2..202610a 100644
--- a/utils/keytable/keytable.c
+++ b/utils/keytable/keytable.c
@@ -123,6 +123,7 @@ const struct protocol_map_entry protocol_map[] = {
 	{ "rc5",	NULL,		SYSFS_RC5	},
 	{ "rc-5x",	NULL,		SYSFS_INVALID	},
 	{ "rc5x",	NULL,		SYSFS_INVALID	},
+	{ "rc-5-sz",	NULL,		SYSFS_RC5_SZ	},
 	{ "jvc",	"/jvc_decoder",	SYSFS_JVC	},
 	{ "sony",	"/sony_decoder",SYSFS_SONY	},
 	{ "sony12",	NULL,		SYSFS_INVALID	},
-- 
2.7.4


^ permalink raw reply related

* [PATCH v4l-utils 2/3] ir-ctl: add verbose option
From: Sean Young @ 2016-11-09 16:13 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: linux-media

This is useful to see what IR is actually being sent (e.g. after
scancode generation).

Signed-off-by: Sean Young <sean@mess.org>
---
 utils/ir-ctl/ir-ctl.1.in |  3 +++
 utils/ir-ctl/ir-ctl.c    | 15 ++++++++++++++-
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/utils/ir-ctl/ir-ctl.1.in b/utils/ir-ctl/ir-ctl.1.in
index 2efe293..a1d5aeb 100644
--- a/utils/ir-ctl/ir-ctl.1.in
+++ b/utils/ir-ctl/ir-ctl.1.in
@@ -99,6 +99,9 @@ Prints the help message
 \fB\-\-usage\fR
 Give a short usage message
 .TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Verbose output; this prints the IR before sending.
+.TP
 \fB\-V\fR, \fB\-\-version\fR
 print the v4l2\-utils version
 .PP
diff --git a/utils/ir-ctl/ir-ctl.c b/utils/ir-ctl/ir-ctl.c
index bdea741..f19bd05 100644
--- a/utils/ir-ctl/ir-ctl.c
+++ b/utils/ir-ctl/ir-ctl.c
@@ -65,6 +65,7 @@ struct arguments {
 	char *device;
 	bool features;
 	bool record;
+	bool verbose;
 	struct file *send;
 	bool oneshot;
 	char *savetofile;
@@ -85,6 +86,7 @@ static const struct argp_option options[] = {
 	{ "record",	'r',	N_("FILE"),	OPTION_ARG_OPTIONAL,	N_("record IR to stdout or file") },
 	{ "send",	's',	N_("FILE"),	0,	N_("send IR pulse and space file") },
 	{ "scancode", 'S',	N_("SCANCODE"),	0,	N_("send IR scancode in protocol specified") },
+	{ "verbose",	'v',	0,		0,	N_("verbose output") },
 		{ .doc = N_("Recording options:") },
 	{ "one-shot",	'1',	0,		0,	N_("end recording after first message") },
 	{ "wideband",	'w',	0,		0,	N_("use wideband receiver aka learning mode") },
@@ -397,6 +399,9 @@ static error_t parse_opt(int k, char *arg, struct argp_state *state)
 	case '1':
 		arguments->oneshot = true;
 		break;
+	case 'v':
+		arguments->verbose = true;
+		break;
 	case 'm':
 		if (arguments->carrier_reports == 2)
 			argp_error(state, _("cannot enable and disable carrier reports"));
@@ -515,7 +520,7 @@ static error_t parse_opt(int k, char *arg, struct argp_state *state)
 		return ARGP_ERR_UNKNOWN;
 	}
 
-	if (k != '1' && k != 'd')
+	if (k != '1' && k != 'd' && k != 'v')
 		arguments->work_to_do = true;
 
 	return 0;
@@ -739,6 +744,12 @@ static int lirc_send(struct arguments *args, int fd, unsigned features, struct f
 		lirc_set_send_carrier(fd, dev, features, f->carrier);
 
 	size_t size = f->len * sizeof(unsigned);
+	if (args->verbose) {
+		int i;
+		printf("Sending:\n");
+		for (i=0; i<f->len; i++)
+			printf("%s %u\n", i & 1 ? "space" : "pulse", f->buf[i]);
+	}
 	ssize_t ret = TEMP_FAILURE_RETRY(write(fd, f->buf, size));
 	if (ret < 0) {
 		fprintf(stderr, _("%s: failed to send: %m\n"), dev);
@@ -752,6 +763,8 @@ static int lirc_send(struct arguments *args, int fd, unsigned features, struct f
 				size / sizeof(unsigned));
 		return EX_IOERR;
 	}
+	if (args->verbose)
+		printf("Successfully sent\n");
 
 	return 0;
 }
-- 
2.7.4


^ permalink raw reply related

* [PATCH] [media] nec decoder: wrong bit order for nec32 protocol
From: Sean Young @ 2016-11-09 16:13 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: linux-media

The bits are sent in lsb first. Hardware decoders also send nec32
in this order (e.g. dib0700). This should be consistent, however
I have no way of knowing which order the LME2510 and Tivo keymaps
are (the only two kernel keymaps with NEC32).

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/media/rc/ir-nec-decoder.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c
index 2a9d155..ba02d05 100644
--- a/drivers/media/rc/ir-nec-decoder.c
+++ b/drivers/media/rc/ir-nec-decoder.c
@@ -170,7 +170,10 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
 		if (send_32bits) {
 			/* NEC transport, but modified protocol, used by at
 			 * least Apple and TiVo remotes */
-			scancode = data->bits;
+			scancode = address     << 24 |
+				   not_address << 16 |
+				   command     << 8 |
+				   not_command;
 			IR_dprintk(1, "NEC (modified) scancode 0x%08x\n", scancode);
 			rc_type = RC_TYPE_NEC32;
 		} else if ((address ^ not_address) != 0xff) {
-- 
2.7.4


^ permalink raw reply related

* [PATCH] [media] sanyo decoder: address was being truncated
From: Sean Young @ 2016-11-09 16:13 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: linux-media

The address is 13 bits but it was stuffed in an u8, so 5 bits are
missing from the scancode.

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/media/rc/ir-sanyo-decoder.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c
index 7331e5e7..b07d9ca 100644
--- a/drivers/media/rc/ir-sanyo-decoder.c
+++ b/drivers/media/rc/ir-sanyo-decoder.c
@@ -56,7 +56,8 @@ static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev)
 {
 	struct sanyo_dec *data = &dev->raw->sanyo;
 	u32 scancode;
-	u8 address, command, not_command;
+	u16 address;
+	u8 command, not_command;
 
 	if (!is_timing_event(ev)) {
 		if (ev.reset) {
-- 
2.7.4


^ permalink raw reply related

* [PATCH v4l-utils 1/3] ir-ctl: add ability to send scancodes in most protocols
From: Sean Young @ 2016-11-09 16:13 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: linux-media

Teach ir-ctl to send scancodes. This has a number of uses:

1. Controlling devices through IR transmission aka blasting
2. Testing the in-kernel software IR decoders (2 bugs uncovered so far)
3. Testing the capability of hardware IR decoders

All protocols supported by the kernel are supported except for XMP
and the MCE Keyboard.

Signed-off-by: Sean Young <sean@mess.org>
---
 utils/ir-ctl/Makefile.am |   2 +-
 utils/ir-ctl/ir-ctl.1.in |  82 ++++++---
 utils/ir-ctl/ir-ctl.c    | 130 ++++++++++++++-
 utils/ir-ctl/ir-encode.c | 427 +++++++++++++++++++++++++++++++++++++++++++++++
 utils/ir-ctl/ir-encode.h |  35 ++++
 5 files changed, 653 insertions(+), 23 deletions(-)
 create mode 100644 utils/ir-ctl/ir-encode.c
 create mode 100644 utils/ir-ctl/ir-encode.h

diff --git a/utils/ir-ctl/Makefile.am b/utils/ir-ctl/Makefile.am
index 9a1bfed..4c148e5 100644
--- a/utils/ir-ctl/Makefile.am
+++ b/utils/ir-ctl/Makefile.am
@@ -1,6 +1,6 @@
 bin_PROGRAMS = ir-ctl
 man_MANS = ir-ctl.1
 
-ir_ctl_SOURCES = ir-ctl.c
+ir_ctl_SOURCES = ir-ctl.c ir-encode.c
 ir_ctl_LDADD = @LIBINTL@
 ir_ctl_LDFLAGS = $(ARGP_LIBS)
diff --git a/utils/ir-ctl/ir-ctl.1.in b/utils/ir-ctl/ir-ctl.1.in
index 4bdf47e..2efe293 100644
--- a/utils/ir-ctl/ir-ctl.1.in
+++ b/utils/ir-ctl/ir-ctl.1.in
@@ -12,10 +12,13 @@ ir\-ctl \- a swiss\-knife tool to handle raw IR and to set lirc options
 [\fIOPTION\fR]... \fI\-\-send\fR [\fIpulse and space file to send\fR]
 .br
 .B ir\-ctl
+[\fIOPTION\fR]... \fI\-\-scancode\fR [\fIprotocol and scancode to send\fR]
+.br
+.B ir\-ctl
 [\fIOPTION\fR]... \fI\-\-record\fR [\fIsave to file\fR]
 .SH DESCRIPTION
 ir\-ctl is a tool that allows one to list the features of a lirc device,
-set its options, record raw IR and send raw IR.
+set its options, record raw IR, send raw IR or send complete IR scancodes.
 .PP
 Note: You need to have read or write permissions on the /dev/lirc device
 for options to work.
@@ -36,6 +39,10 @@ Send IR in text file. It must be in the format described below. If this
 option is specified multiple times, send all files in order with 125ms delay
 between them.
 .TP
+\fB-S\fR, \fB\-\-scancode\fR=\fIPROTOCOL:SCANCODE\fR
+Send the IR scancode in the protocol specified. The protocol must one of
+the protocols listed below, followed by a semicolon and the scancode number.
+.TP
 \fB\-1\fR, \fB\-\-oneshot\fR
 When recording, stop recording after the first message, i.e. after a space or
 timeout of more than 19ms is received.
@@ -106,43 +113,74 @@ by length in microseconds. The following is a rc-5 encoded message:
 .PP
 	carrier 36000
 .br
-	pulse 920
+	pulse 940
+.br
+	space 860
+.br
+	pulse 1790
+.br
+	space 1750
+.br
+	pulse 880
 .br
-	space 110
+	space 880
 .br
-	pulse 270
+	pulse 900
 .br
-	space 380
+	space 890
 .br
-	pulse 1800
+	pulse 870
 .br
-	space 1560
+	space 900
 .br
-	pulse 1730
+	pulse 1750
 .br
-	space 1630
+	space 900
 .br
-	pulse 1730
+	pulse 890
 .br
-	space 1640
+	space 910
 .br
-	pulse 850
+	pulse 840
 .br
-	space 830
+	space 920
 .br
-	pulse 1690
+	pulse 870
 .br
-	space 820
+	space 920
 .br
-	pulse 860
+	pulse 840
 .br
-	space 1660
+	space 920
 .br
-	pulse 1690
+	pulse 870
 .br
-	space 830
+	space 1810
 .br
-	pulse 850
+	pulse 840
+.PP
+Rather than specifying the raw IR, you can also specify the scancode and
+protocol you want to send. This will also automatically set the correct
+carrier. The above can be written as:
+.PP
+	scancode rc5:0x1e01
+.PP
+Do not specify scancodes with different protocols in one file, as the
+carrier might differ and the transmitter cannot send this. Multiple
+scancodes can be specified in one file but ensure that the rules for the
+protocol are met by inserting an appropriate space between them. Also,
+there are limits to what lirc devices can send in one go.
+.PP
+.SS Supported Protocols
+A scancode with protocol can be specified on the command line or in the
+pulse and space file. The following protocols are supported:
+\fBrc5\fR, \fBrc5x\fR, \fBrc5_sz\fR, \fBjvc\fR, \fBsony12\fR, \fBsony\fB15\fR,
+\fBsony20\fR, \fBnec\fR, \fBnecx\fR, \fBnec32\fR, \fBsanyo\fR, \fBrc6_0\fR,
+\fBrc6_6a_20\fR, \fBrc6_6a_24\fR, \fBrc6_6a_32\fR, \fBrc6_mce\fR, \fBsharp\fR.
+If the scancode starts with 0x it will be interpreted as a
+hexidecimal number, and if it starts with 0 it will be interpreted as an
+octal number.
+.PP
 .SS Wideband and narrowband receiver
 Most IR receivers have a narrowband and wideband receiver. The narrowband
 receiver can receive over longer distances (usually around 10 metres without
@@ -178,6 +216,10 @@ To send the pulse and space file \fBplay\fR on emitter 3:
 .br
 	\fBir\-ctl \-e 3 \-\-send=play\fR
 .PP
+To send the rc-5 hauppuage '1' scancode:
+.br
+	\fBir\-ctl \-S rc5:0x1e01
+.PP
 To restore the IR receiver on /dev/lirc2 to the default state:
 .br
 	\fBir\-ctl \-PMn \-\-timeout 125000 \-\-device=/dev/lirc2\fR
diff --git a/utils/ir-ctl/ir-ctl.c b/utils/ir-ctl/ir-ctl.c
index 2f85e6d..bdea741 100644
--- a/utils/ir-ctl/ir-ctl.c
+++ b/utils/ir-ctl/ir-ctl.c
@@ -26,6 +26,8 @@
 
 #include <config.h>
 
+#include "ir-encode.h"
+
 #include <linux/lirc.h>
 
 #ifdef ENABLE_NLS
@@ -82,6 +84,7 @@ static const struct argp_option options[] = {
 	{ "features",	'f',	0,		0,	N_("list lirc device features") },
 	{ "record",	'r',	N_("FILE"),	OPTION_ARG_OPTIONAL,	N_("record IR to stdout or file") },
 	{ "send",	's',	N_("FILE"),	0,	N_("send IR pulse and space file") },
+	{ "scancode", 'S',	N_("SCANCODE"),	0,	N_("send IR scancode in protocol specified") },
 		{ .doc = N_("Recording options:") },
 	{ "one-shot",	'1',	0,		0,	N_("end recording after first message") },
 	{ "wideband",	'w',	0,		0,	N_("use wideband receiver aka learning mode") },
@@ -103,6 +106,7 @@ static const char args_doc[] = N_(
 	"--features\n"
 	"--record [save to file]\n"
 	"--send [file to send]\n"
+	"--scancode [scancode to send]\n"
 	"[to set lirc option]");
 
 static const char doc[] = N_(
@@ -115,7 +119,8 @@ static const char doc[] = N_(
 	"  DUTY     - the duty cycle to use for sending\n"
 	"  EMITTERS - comma separated list of emitters to use for sending, e.g. 1,2\n"
 	"  RANGE    - set range of accepted carrier frequencies, e.g. 20000-40000\n"
-	"  TIMEOUT  - set length of space before recording stops in microseonds\n\n"
+	"  TIMEOUT  - set length of space before recording stops in microseconds\n"
+	"  SCANCODE - protocol:scancode, e.g. nec:0xa814\n\n"
 	"Note that most lirc setting have global state, i.e. the device will remain\n"
 	"in this state until set otherwise.");
 
@@ -132,6 +137,20 @@ static int strtoint(const char *p, const char *unit)
 	return arg;
 }
 
+static bool strtoscancode(const char *p, unsigned *ret)
+{
+	char *end;
+	long arg = strtol(p, &end, 0);
+	if (end == NULL || end[0] != 0)
+		return false;
+
+	if (arg <= 0 || arg >= 0xffffffff)
+		return false;
+
+	*ret = arg;
+	return true;
+}
+
 static unsigned parse_emitters(char *p)
 {
 	unsigned emit = 0;
@@ -193,6 +212,54 @@ static struct file *read_file(const char *fname)
 			continue;
 		}
 
+		if (strcmp(keyword, "scancode") == 0) {
+			enum rc_proto proto;
+			unsigned scancode, carrier;
+			char *scancodestr;
+
+			if (!expect_pulse) {
+				fprintf(stderr, _("error: %s:%d: space must precede scancode\n"), fname, lineno);
+				return NULL;
+			}
+
+			scancodestr = strchr(p, ':');
+			if (!scancodestr) {
+				fprintf(stderr, _("error: %s:%d: scancode argument '%s' should in protocol:scancode format\n"), fname, lineno, p);
+				return NULL;
+			}
+
+			*scancodestr++ = 0;
+
+			if (!protocol_match(p, &proto)) {
+				fprintf(stderr, _("error: %s:%d: protocol '%s' not found\n"), fname, lineno, p);
+				return NULL;
+			}
+
+			if (!strtoscancode(scancodestr, &scancode)) {
+				fprintf(stderr, _("error: %s:%d: invalid scancode '%s'\n"), fname, lineno, scancodestr);
+				return NULL;
+			}
+
+			if (scancode & ~protocol_scancode_mask(proto)) {
+				fprintf(stderr, _("error: %s:%d: invalid scancode '%s' for protocol '%s'\n"), fname, lineno, scancodestr, protocol_name(proto));
+				return NULL;
+			}
+
+			if (len + protocol_max_size(proto) >= LIRCBUF_SIZE) {
+				fprintf(stderr, _("error: %s:%d: too much IR for one transmit\n"), fname, lineno);
+				return NULL;
+			}
+
+			carrier = protocol_carrier(proto);
+			if (f->carrier && f->carrier != carrier)
+				fprintf(stderr, _("error: %s:%d: carrier already specified\n"), fname, lineno);
+			else
+				f->carrier = carrier;
+
+			len += protocol_encode(proto, scancode, f->buf);
+			continue;
+		}
+
 		int arg = strtoint(p, "");
 		if (arg == 0) {
 			fprintf(stderr, _("warning: %s:%d: invalid argument '%s'\n"), fname, lineno, p);
@@ -225,7 +292,7 @@ static struct file *read_file(const char *fname)
 				f->buf[len++] = arg;
 			expect_pulse = false;
 		} else if (strcmp(keyword, "carrier") == 0) {
-			if (f->carrier) {
+			if (f->carrier && f->carrier != arg) {
 				fprintf(stderr, _("warning: %s:%d: carrier already specified\n"), fname, lineno);
 			} else {
 				f->carrier = arg;
@@ -260,6 +327,48 @@ static struct file *read_file(const char *fname)
 	return f;
 }
 
+static struct file *read_scancode(const char *name)
+{
+	enum rc_proto proto;
+	struct file *f;
+	unsigned scancode;
+	char *pstr;
+	char *p = strchr(name, ':');
+
+	if (!p) {
+		fprintf(stderr, _("error: scancode '%s' most be in protocol:scancode format\n"), name);
+		return NULL;
+	}
+
+	pstr = strndupa(name, p - name);
+
+	if (!protocol_match(pstr, &proto)) {
+		fprintf(stderr, _("error: protocol '%s' not found\n"), pstr);
+		return NULL;
+	}
+
+	if (!strtoscancode(p + 1, &scancode)) {
+		fprintf(stderr, _("error: invalid scancode '%s'\n"), p + 1);
+		return NULL;
+	}
+
+	if (scancode & ~protocol_scancode_mask(proto)) {
+		fprintf(stderr, _("error: invalid scancode '%s' for protocol '%s'\n"), p + 1, protocol_name(proto));
+		return NULL;
+	}
+
+	f = malloc(sizeof(*f));
+	if (f == NULL) {
+		fprintf(stderr, _("Failed to allocate memory\n"));
+		return NULL;
+	}
+
+	f->carrier = protocol_carrier(proto);
+	f->fname = name;
+	f->len = protocol_encode(proto, scancode, f->buf);
+
+	return f;
+}
 
 static error_t parse_opt(int k, char *arg, struct argp_state *state)
 {
@@ -380,6 +489,23 @@ static error_t parse_opt(int k, char *arg, struct argp_state *state)
 			p->next = s;
 		}
 		break;
+	case 'S':
+		if (arguments->record || arguments->features)
+			argp_error(state, _("send can not be combined with record or features option"));
+		s = read_scancode(arg);
+		if (s == NULL)
+			exit(EX_DATAERR);
+
+		s->next = NULL;
+		if (arguments->send == NULL)
+			arguments->send = s;
+		else {
+			struct file *p = arguments->send;
+			while (p->next) p = p->next;
+			p->next = s;
+		}
+		break;
+
 	case ARGP_KEY_END:
 		if (!arguments->work_to_do)
 			argp_usage(state);
diff --git a/utils/ir-ctl/ir-encode.c b/utils/ir-ctl/ir-encode.c
new file mode 100644
index 0000000..a0d2f4c
--- /dev/null
+++ b/utils/ir-ctl/ir-encode.c
@@ -0,0 +1,427 @@
+/*
+ * ir-encode.c - encodes IR scancodes in different protocols
+ *
+ * Copyright (C) 2016 Sean Young <sean@mess.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * TODO: XMP protocol and MCE keyboard
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <ctype.h>
+
+#include "ir-encode.h"
+
+#define NS_TO_US(x) (((x)+500)/1000)
+
+static int nec_encode(enum rc_proto proto, unsigned scancode, unsigned *buf)
+{
+	const int nec_unit = 562500;
+	int n = 0;
+
+	void add_byte(unsigned bits)
+	{
+		int i;
+		for (i=0; i<8; i++) {
+			buf[n++] = NS_TO_US(nec_unit);
+			if (bits & (1 << i))
+				buf[n++] = NS_TO_US(nec_unit * 3);
+			else
+				buf[n++] = NS_TO_US(nec_unit);
+		}
+	}
+
+	buf[n++] = NS_TO_US(nec_unit * 16);
+	buf[n++] = NS_TO_US(nec_unit * 8);
+
+	switch (proto) {
+	default:
+		return 0;
+	case RC_PROTO_NEC:
+		add_byte(scancode >> 8);
+		add_byte(~(scancode >> 8));
+		add_byte(scancode);
+		add_byte(~scancode);
+		break;
+	case RC_PROTO_NECX:
+		add_byte(scancode >> 16);
+		add_byte(scancode >> 8);
+		add_byte(scancode);
+		add_byte(~scancode);
+		break;
+	case RC_PROTO_NEC32:
+		/*
+		 * At the time of writing kernel software nec decoder
+		 * reverses the bit order so it will not match. Hardware
+		 * decoders do not have this issue.
+		 */
+		add_byte(scancode >> 24);
+		add_byte(scancode >> 16);
+		add_byte(scancode >> 8);
+		add_byte(scancode);
+		break;
+	}
+
+	buf[n++] = NS_TO_US(nec_unit);
+
+	return n;
+}
+
+static int jvc_encode(enum rc_proto proto, unsigned scancode, unsigned *buf)
+{
+	const int jvc_unit = 525000;
+	int i;
+
+	/* swap bytes so address comes first */
+	scancode = ((scancode << 8) & 0xff00) | ((scancode >> 8) & 0x00ff);
+
+	*buf++ = NS_TO_US(jvc_unit * 16);
+	*buf++ = NS_TO_US(jvc_unit * 8);
+
+	for (i=0; i<16; i++) {
+		*buf++ = NS_TO_US(jvc_unit);
+
+		if (scancode & 1)
+			*buf++ = NS_TO_US(jvc_unit * 3);
+		else
+			*buf++ = NS_TO_US(jvc_unit);
+
+		scancode >>= 1;
+	}
+
+	*buf = NS_TO_US(jvc_unit);
+
+	return 35;
+}
+
+static int sanyo_encode(enum rc_proto proto, unsigned scancode, unsigned *buf)
+{
+	const int sanyo_unit = 562500;
+
+	void add_bits(int bits, int count)
+	{
+		int i;
+		for (i=0; i<count; i++) {
+			*buf++ = NS_TO_US(sanyo_unit);
+
+			if (bits & (1 << i))
+				*buf++ = NS_TO_US(sanyo_unit * 3);
+			else
+				*buf++ = NS_TO_US(sanyo_unit);
+		}
+	}
+
+	*buf++ = NS_TO_US(sanyo_unit * 16);
+	*buf++ = NS_TO_US(sanyo_unit * 8);
+
+	add_bits(scancode >> 8, 13);
+	add_bits(~(scancode >> 8), 13);
+	add_bits(scancode, 8);
+	add_bits(~scancode, 8);
+
+	*buf = NS_TO_US(sanyo_unit);
+
+	return 87;
+}
+
+static int sharp_encode(enum rc_proto proto, unsigned scancode, unsigned *buf)
+{
+	const int sharp_unit = 40000;
+
+	void add_bits(int bits, int count)
+	{
+		int i;
+		for (i=0; i<count; i++) {
+			*buf++ = NS_TO_US(sharp_unit * 8);
+
+			if (bits & (1 << i))
+				*buf++ = NS_TO_US(sharp_unit * 50);
+			else
+				*buf++ = NS_TO_US(sharp_unit * 25);
+		}
+	}
+
+	add_bits(scancode >> 8, 5);
+	add_bits(scancode, 8);
+	add_bits(1, 2);
+
+	*buf++ = NS_TO_US(sharp_unit * 8);
+	*buf++ = NS_TO_US(sharp_unit * 1000);
+
+	add_bits(scancode >> 8, 5);
+	add_bits(~scancode, 8);
+	add_bits(~1, 2);
+	*buf++ = NS_TO_US(sharp_unit * 8);
+
+	return (13 + 2) * 4 + 3;
+}
+
+static int sony_encode(enum rc_proto proto, unsigned scancode, unsigned *buf)
+{
+	const int sony_unit = 600000;
+	int n = 0;
+
+	void add_bits(int bits, int count)
+	{
+		int i;
+		for (i=0; i<count; i++) {
+			if (bits & (1 << i))
+				buf[n++] = NS_TO_US(sony_unit * 2);
+			else
+				buf[n++] = NS_TO_US(sony_unit);
+
+			buf[n++] = NS_TO_US(sony_unit);
+		}
+	}
+
+	buf[n++] = NS_TO_US(sony_unit * 4);
+	buf[n++] = NS_TO_US(sony_unit);
+
+	switch (proto) {
+	case RC_PROTO_SONY12:
+		add_bits(scancode, 7);
+		add_bits(scancode >> 16, 5);
+		break;
+	case RC_PROTO_SONY15:
+		add_bits(scancode, 7);
+		add_bits(scancode >> 16, 8);
+		break;
+	case RC_PROTO_SONY20:
+		add_bits(scancode, 7);
+		add_bits(scancode >> 16, 5);
+		add_bits(scancode >> 8, 8);
+		break;
+	default:
+		return 0;
+	}
+
+	/* ignore last space */
+	return n - 1;
+}
+
+static int rc5_encode(enum rc_proto proto, unsigned scancode, unsigned *buf)
+{
+	const unsigned int rc5_unit = 888888;
+	unsigned n = 0;
+
+	void advance_space(unsigned length)
+	{
+		if (n % 2)
+			buf[n] += length;
+		else
+			buf[++n] = length;
+	}
+
+	void advance_pulse(unsigned length)
+	{
+		if (n % 2)
+			buf[++n] = length;
+		else
+			buf[n] += length;
+	}
+
+	void add_bits(int bits, int count)
+	{
+		while (count--) {
+			if (bits & (1 << count)) {
+				advance_space(NS_TO_US(rc5_unit));
+				advance_pulse(NS_TO_US(rc5_unit));
+			} else {
+				advance_pulse(NS_TO_US(rc5_unit));
+				advance_space(NS_TO_US(rc5_unit));
+			}
+		}
+	}
+
+	buf[n] = NS_TO_US(rc5_unit);
+
+	switch (proto) {
+	default:
+		return 0;
+	case RC_PROTO_RC5:
+		add_bits(2, 2);
+		add_bits(scancode >> 8, 5);
+		add_bits(scancode, 6);
+		break;
+	case RC_PROTO_RC5_SZ:
+		add_bits(!!(scancode & 0x2000), 1);
+		add_bits(0, 1);
+		add_bits(scancode >> 6, 6);
+		add_bits(scancode, 6);
+		break;
+	case RC_PROTO_RC5X:
+		add_bits(!!(scancode & 0x4000), 1);
+		add_bits(0, 1);
+		add_bits(scancode >> 16, 5);
+		advance_space(NS_TO_US(rc5_unit * 4));
+		add_bits(scancode >> 8, 6);
+		add_bits(scancode, 6);
+		break;
+	}
+
+	/* drop any trailing pulse */
+	return (n % 2) ? n : n + 1;
+}
+
+static int rc6_encode(enum rc_proto proto, unsigned scancode, unsigned *buf)
+{
+	const unsigned int rc6_unit = 444444;
+	unsigned n = 0;
+
+	void advance_space(unsigned length)
+	{
+		if (n % 2)
+			buf[n] += length;
+		else
+			buf[++n] = length;
+	}
+
+	void advance_pulse(unsigned length)
+	{
+		if (n % 2)
+			buf[++n] = length;
+		else
+			buf[n] += length;
+	}
+
+	void add_bits(unsigned bits, unsigned count, unsigned length)
+	{
+		while (count--) {
+			if (bits & (1 << count)) {
+				advance_pulse(length);
+				advance_space(length);
+			} else {
+				advance_space(length);
+				advance_pulse(length);
+			}
+		}
+	}
+
+	buf[n++] = NS_TO_US(rc6_unit * 6);
+	buf[n++] = NS_TO_US(rc6_unit * 2);
+
+	switch (proto) {
+	default:
+		return 0;
+	case RC_PROTO_RC6_0:
+		add_bits(8, 4, NS_TO_US(rc6_unit));
+		add_bits(0, 1, NS_TO_US(rc6_unit * 2));
+		add_bits(scancode, 16, NS_TO_US(rc6_unit));
+		break;
+	case RC_PROTO_RC6_6A_20:
+		add_bits(14, 4, NS_TO_US(rc6_unit));
+		add_bits(0, 1, NS_TO_US(rc6_unit * 2));
+		add_bits(scancode, 20, NS_TO_US(rc6_unit));
+		break;
+	case RC_PROTO_RC6_6A_24:
+		add_bits(14, 4, NS_TO_US(rc6_unit));
+		add_bits(0, 1, NS_TO_US(rc6_unit * 2));
+		add_bits(scancode, 24, NS_TO_US(rc6_unit));
+		break;
+	case RC_PROTO_RC6_6A_32:
+	case RC_PROTO_RC6_MCE:
+		add_bits(14, 4, NS_TO_US(rc6_unit));
+		add_bits(0, 1, NS_TO_US(rc6_unit * 2));
+		add_bits(scancode, 32, NS_TO_US(rc6_unit));
+		break;
+	}
+
+	/* drop any trailing pulse */
+	return (n % 2) ? n : n + 1;
+}
+
+static const struct {
+	char name[10];
+	unsigned scancode_mask;
+	unsigned max_edges;
+	unsigned carrier;
+	int (*encode)(enum rc_proto proto, unsigned scancode, unsigned *buf);
+} encoders[RC_PROTO_COUNT] = {
+	[RC_PROTO_RC5] = { "rc5", 0x1f3f, 24, 36000, rc5_encode },
+	[RC_PROTO_RC5X] = { "rc5x", 0x1f3f3f, 40, 36000, rc5_encode },
+	[RC_PROTO_RC5_SZ] = { "rc5_sz", 0x2fff, 26, 36000, rc5_encode },
+	[RC_PROTO_SONY12] = { "sony12", 0x1f007f, 25, 40000, sony_encode },
+	[RC_PROTO_SONY15] = { "sony15", 0xff007f, 31, 40000, sony_encode },
+	[RC_PROTO_SONY20] = { "sony20", 0x1fff7f, 41, 40000, sony_encode },
+	[RC_PROTO_JVC] = { "jvc", 0xffff, 35, 38000, jvc_encode },
+	[RC_PROTO_NEC] = { "nec", 0xffff, 67, 38000, nec_encode },
+	[RC_PROTO_NECX] = { "necx", 0xffffff, 67, 38000, nec_encode },
+	[RC_PROTO_NEC32] = { "nec32", 0xffffffff, 67, 38000, nec_encode },
+	[RC_PROTO_SANYO] = { "sanyo", 0x1fffff, 87, 38000, sanyo_encode },
+	[RC_PROTO_RC6_0] = { "rc6_0", 0xffff, 24, 36000, rc6_encode },
+	[RC_PROTO_RC6_6A_20] = { "rc6_6a_20", 0xfffff, 52, 36000, rc6_encode },
+	[RC_PROTO_RC6_6A_24] = { "rc6_6a_24", 0xffffff, 60, 36000, rc6_encode },
+	[RC_PROTO_RC6_6A_32] = { "rc6_6a_32", 0xffffffff, 76, 36000, rc6_encode },
+	[RC_PROTO_RC6_MCE] = { "rc6_mce", 0xffff7fff, 76, 36000, rc6_encode },
+	[RC_PROTO_SHARP] = { "sharp", 0x1fff, 63, 38000, sharp_encode },
+};
+
+static bool str_like(const char *a, const char *b)
+{
+	while (*a && *b) {
+		while (*a == ' ' || *a == '-' || *a == '_')
+			a++;
+		while (*b == ' ' || *b == '-' || *b == '_')
+			b++;
+
+		if (*a >= 0x7f || *b >= 0x7f)
+			return false;
+
+		if (tolower(*a) != tolower(*b))
+			return false;
+
+		a++; b++;
+	}
+
+	return !*a && !*b;
+}
+
+bool protocol_match(const char *name, enum rc_proto *proto)
+{
+	enum rc_proto p;
+
+	for (p=0; p<RC_PROTO_COUNT; p++) {
+		if (str_like(encoders[p].name, name)) {
+			*proto = p;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+unsigned protocol_carrier(enum rc_proto proto)
+{
+	return encoders[proto].carrier;
+}
+
+unsigned protocol_max_size(enum rc_proto proto)
+{
+	return encoders[proto].max_edges;
+}
+
+unsigned protocol_scancode_mask(enum rc_proto proto)
+{
+	return encoders[proto].scancode_mask;
+}
+
+unsigned protocol_encode(enum rc_proto proto, unsigned scancode, unsigned *buf)
+{
+	return encoders[proto].encode(proto, scancode, buf);
+}
+
+const char* protocol_name(enum rc_proto proto)
+{
+	return encoders[proto].name;
+}
diff --git a/utils/ir-ctl/ir-encode.h b/utils/ir-ctl/ir-encode.h
new file mode 100644
index 0000000..b2542ec
--- /dev/null
+++ b/utils/ir-ctl/ir-encode.h
@@ -0,0 +1,35 @@
+
+#ifndef __IR_ENCODE_H__
+#define __IR_ENCODE_H__
+
+enum rc_proto {
+	RC_PROTO_RC5,
+	RC_PROTO_RC5X,
+	RC_PROTO_RC5_SZ,
+	RC_PROTO_JVC,
+	RC_PROTO_SONY12,
+	RC_PROTO_SONY15,
+	RC_PROTO_SONY20,
+	RC_PROTO_NEC,
+	RC_PROTO_NECX,
+	RC_PROTO_NEC32,
+	RC_PROTO_SANYO,
+	RC_PROTO_MCE_KBD,
+	RC_PROTO_RC6_0,
+	RC_PROTO_RC6_6A_20,
+	RC_PROTO_RC6_6A_24,
+	RC_PROTO_RC6_6A_32,
+	RC_PROTO_RC6_MCE,
+	RC_PROTO_SHARP,
+	RC_PROTO_XMP,
+	RC_PROTO_COUNT
+};
+
+bool protocol_match(const char *name, enum rc_proto *proto);
+unsigned protocol_carrier(enum rc_proto proto);
+unsigned protocol_max_size(enum rc_proto proto);
+unsigned protocol_scancode_mask(enum rc_proto proto);
+unsigned protocol_encode(enum rc_proto proto, unsigned scancode, unsigned *buf);
+const char *protocol_name(enum rc_proto proto);
+
+#endif
-- 
2.7.4


^ permalink raw reply related

* [BACKPORT PATCH 3.18..4.4] KVM: MIPS: Precalculate MMIO load resume PC
From: James Hogan @ 2016-11-09 16:12 UTC (permalink / raw)
  To: stable
  Cc: Paolo Bonzini, Radim Krčmář, Ralf Baechle,
	linux-mips, kvm, James Hogan

commit e1e575f6b026734be3b1f075e780e91ab08ca541 upstream.

The advancing of the PC when completing an MMIO load is done before
re-entering the guest, i.e. before restoring the guest ASID. However if
the load is in a branch delay slot it may need to access guest code to
read the prior branch instruction. This isn't safe in TLB mapped code at
the moment, nor in the future when we'll access unmapped guest segments
using direct user accessors too, as it could read the branch from host
user memory instead.

Therefore calculate the resume PC in advance while we're still in the
right context and save it in the new vcpu->arch.io_pc (replacing the no
longer needed vcpu->arch.pending_load_cause), and restore it on MMIO
completion.

Fixes: e685c689f3a8 ("KVM/MIPS32: Privileged instruction/target branch emulation.")
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Radim Krčmář <rkrcmar@redhat.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
Cc: kvm@vger.kernel.org
Cc: <stable@vger.kernel.org> # 3.18.x-4.0.x: 5f508c43a764: MIPS: KVM: Fix unused variable build warning
Cc: <stable@vger.kernel.org> # 3.18.x-4.4.x
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[james.hogan@imgtec.com: Backport to 3.18..4.4]
Signed-off-by: James Hogan <james.hogan@imgtec.com>
---
 arch/mips/include/asm/kvm_host.h |  7 ++++---
 arch/mips/kvm/emulate.c          | 24 +++++++++++++++---------
 2 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h
index dd7cee795709..c8c04a1f1c9f 100644
--- a/arch/mips/include/asm/kvm_host.h
+++ b/arch/mips/include/asm/kvm_host.h
@@ -400,7 +400,10 @@ struct kvm_vcpu_arch {
 	/* Host KSEG0 address of the EI/DI offset */
 	void *kseg0_commpage;
 
-	u32 io_gpr;		/* GPR used as IO source/target */
+	/* Resume PC after MMIO completion */
+	unsigned long io_pc;
+	/* GPR used as IO source/target */
+	u32 io_gpr;
 
 	struct hrtimer comparecount_timer;
 	/* Count timer control KVM register */
@@ -422,8 +425,6 @@ struct kvm_vcpu_arch {
 	/* Bitmask of pending exceptions to be cleared */
 	unsigned long pending_exceptions_clr;
 
-	unsigned long pending_load_cause;
-
 	/* Save/Restore the entryhi register when are are preempted/scheduled back in */
 	unsigned long preempt_entryhi;
 
diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c
index 03344f5ec499..85c7d36e7e1c 100644
--- a/arch/mips/kvm/emulate.c
+++ b/arch/mips/kvm/emulate.c
@@ -1473,6 +1473,7 @@ enum emulation_result kvm_mips_emulate_load(uint32_t inst, uint32_t cause,
 					    struct kvm_vcpu *vcpu)
 {
 	enum emulation_result er = EMULATE_DO_MMIO;
+	unsigned long curr_pc;
 	int32_t op, base, rt, offset;
 	uint32_t bytes;
 
@@ -1481,7 +1482,18 @@ enum emulation_result kvm_mips_emulate_load(uint32_t inst, uint32_t cause,
 	offset = inst & 0xffff;
 	op = (inst >> 26) & 0x3f;
 
-	vcpu->arch.pending_load_cause = cause;
+	/*
+	 * Find the resume PC now while we have safe and easy access to the
+	 * prior branch instruction, and save it for
+	 * kvm_mips_complete_mmio_load() to restore later.
+	 */
+	curr_pc = vcpu->arch.pc;
+	er = update_pc(vcpu, cause);
+	if (er == EMULATE_FAIL)
+		return er;
+	vcpu->arch.io_pc = vcpu->arch.pc;
+	vcpu->arch.pc = curr_pc;
+
 	vcpu->arch.io_gpr = rt;
 
 	switch (op) {
@@ -2461,9 +2473,8 @@ enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu,
 		goto done;
 	}
 
-	er = update_pc(vcpu, vcpu->arch.pending_load_cause);
-	if (er == EMULATE_FAIL)
-		return er;
+	/* Restore saved resume PC */
+	vcpu->arch.pc = vcpu->arch.io_pc;
 
 	switch (run->mmio.len) {
 	case 4:
@@ -2485,11 +2496,6 @@ enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu,
 		break;
 	}
 
-	if (vcpu->arch.pending_load_cause & CAUSEF_BD)
-		kvm_debug("[%#lx] Completing %d byte BD Load to gpr %d (0x%08lx) type %d\n",
-			  vcpu->arch.pc, run->mmio.len, vcpu->arch.io_gpr, *gpr,
-			  vcpu->mmio_needed);
-
 done:
 	return er;
 }
-- 
2.10.1

^ permalink raw reply related

* [BACKPORT PATCH 3.18..4.4] KVM: MIPS: Precalculate MMIO load resume PC
From: James Hogan @ 2016-11-09 16:12 UTC (permalink / raw)
  To: stable
  Cc: Paolo Bonzini, Radim Krčmář, Ralf Baechle,
	linux-mips, kvm, James Hogan

commit e1e575f6b026734be3b1f075e780e91ab08ca541 upstream.

The advancing of the PC when completing an MMIO load is done before
re-entering the guest, i.e. before restoring the guest ASID. However if
the load is in a branch delay slot it may need to access guest code to
read the prior branch instruction. This isn't safe in TLB mapped code at
the moment, nor in the future when we'll access unmapped guest segments
using direct user accessors too, as it could read the branch from host
user memory instead.

Therefore calculate the resume PC in advance while we're still in the
right context and save it in the new vcpu->arch.io_pc (replacing the no
longer needed vcpu->arch.pending_load_cause), and restore it on MMIO
completion.

Fixes: e685c689f3a8 ("KVM/MIPS32: Privileged instruction/target branch emulation.")
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Radim Krčmář <rkrcmar@redhat.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
Cc: kvm@vger.kernel.org
Cc: <stable@vger.kernel.org> # 3.18.x-4.0.x: 5f508c43a764: MIPS: KVM: Fix unused variable build warning
Cc: <stable@vger.kernel.org> # 3.18.x-4.4.x
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[james.hogan@imgtec.com: Backport to 3.18..4.4]
Signed-off-by: James Hogan <james.hogan@imgtec.com>
---
 arch/mips/include/asm/kvm_host.h |  7 ++++---
 arch/mips/kvm/emulate.c          | 24 +++++++++++++++---------
 2 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h
index dd7cee795709..c8c04a1f1c9f 100644
--- a/arch/mips/include/asm/kvm_host.h
+++ b/arch/mips/include/asm/kvm_host.h
@@ -400,7 +400,10 @@ struct kvm_vcpu_arch {
 	/* Host KSEG0 address of the EI/DI offset */
 	void *kseg0_commpage;
 
-	u32 io_gpr;		/* GPR used as IO source/target */
+	/* Resume PC after MMIO completion */
+	unsigned long io_pc;
+	/* GPR used as IO source/target */
+	u32 io_gpr;
 
 	struct hrtimer comparecount_timer;
 	/* Count timer control KVM register */
@@ -422,8 +425,6 @@ struct kvm_vcpu_arch {
 	/* Bitmask of pending exceptions to be cleared */
 	unsigned long pending_exceptions_clr;
 
-	unsigned long pending_load_cause;
-
 	/* Save/Restore the entryhi register when are are preempted/scheduled back in */
 	unsigned long preempt_entryhi;
 
diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c
index 03344f5ec499..85c7d36e7e1c 100644
--- a/arch/mips/kvm/emulate.c
+++ b/arch/mips/kvm/emulate.c
@@ -1473,6 +1473,7 @@ enum emulation_result kvm_mips_emulate_load(uint32_t inst, uint32_t cause,
 					    struct kvm_vcpu *vcpu)
 {
 	enum emulation_result er = EMULATE_DO_MMIO;
+	unsigned long curr_pc;
 	int32_t op, base, rt, offset;
 	uint32_t bytes;
 
@@ -1481,7 +1482,18 @@ enum emulation_result kvm_mips_emulate_load(uint32_t inst, uint32_t cause,
 	offset = inst & 0xffff;
 	op = (inst >> 26) & 0x3f;
 
-	vcpu->arch.pending_load_cause = cause;
+	/*
+	 * Find the resume PC now while we have safe and easy access to the
+	 * prior branch instruction, and save it for
+	 * kvm_mips_complete_mmio_load() to restore later.
+	 */
+	curr_pc = vcpu->arch.pc;
+	er = update_pc(vcpu, cause);
+	if (er == EMULATE_FAIL)
+		return er;
+	vcpu->arch.io_pc = vcpu->arch.pc;
+	vcpu->arch.pc = curr_pc;
+
 	vcpu->arch.io_gpr = rt;
 
 	switch (op) {
@@ -2461,9 +2473,8 @@ enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu,
 		goto done;
 	}
 
-	er = update_pc(vcpu, vcpu->arch.pending_load_cause);
-	if (er == EMULATE_FAIL)
-		return er;
+	/* Restore saved resume PC */
+	vcpu->arch.pc = vcpu->arch.io_pc;
 
 	switch (run->mmio.len) {
 	case 4:
@@ -2485,11 +2496,6 @@ enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu,
 		break;
 	}
 
-	if (vcpu->arch.pending_load_cause & CAUSEF_BD)
-		kvm_debug("[%#lx] Completing %d byte BD Load to gpr %d (0x%08lx) type %d\n",
-			  vcpu->arch.pc, run->mmio.len, vcpu->arch.io_gpr, *gpr,
-			  vcpu->mmio_needed);
-
 done:
 	return er;
 }
-- 
2.10.1

^ permalink raw reply related

* [PATCH] doc: postpone ABI changes for mbuf
From: Olivier Matz @ 2016-11-09 16:12 UTC (permalink / raw)
  To: dev, john.mcnamara

Mbuf modifications are not ready for 16.11, postpone them to 17.02.

Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
 doc/guides/rel_notes/deprecation.rst | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 9f5fa55..1a9e1ae 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -15,16 +15,17 @@ Deprecation Notices
   ``nb_seg_max`` and ``nb_mtu_seg_max`` providing information about number of
   segments limit to be transmitted by device for TSO/non-TSO packets.
 
-* ABI changes are planned for 16.11 in the ``rte_mbuf`` structure: some fields
+* ABI changes are planned for 17.02 in the ``rte_mbuf`` structure: some fields
   may be reordered to facilitate the writing of ``data_off``, ``refcnt``, and
   ``nb_segs`` in one operation, because some platforms have an overhead if the
   store address is not naturally aligned. Other mbuf fields, such as the
-  ``port`` field, may be moved or removed as part of this mbuf work.
+  ``port`` field, may be moved or removed as part of this mbuf work. A
+  ``timestamp`` will also be added.
 
 * The mbuf flags PKT_RX_VLAN_PKT and PKT_RX_QINQ_PKT are deprecated and
   are respectively replaced by PKT_RX_VLAN_STRIPPED and
   PKT_RX_QINQ_STRIPPED, that are better described. The old flags and
-  their behavior will be kept in 16.07 and will be removed in 16.11.
+  their behavior will be kept until 16.11 and will be removed in 17.02.
 
 * mempool: The functions ``rte_mempool_count`` and ``rte_mempool_free_count``
   will be removed in 17.02.
-- 
2.8.1

^ permalink raw reply related

* Re: [PATCH 2/4] mfd: palmas: Reset the POWERHOLD mux during power off
From: Lee Jones @ 2016-11-09 16:14 UTC (permalink / raw)
  To: Keerthy
  Cc: tony, robh+dt, linux-omap, linux-kernel, devicetree, linux-gpio,
	nm, t-kristo
In-Reply-To: <1477559414-12520-3-git-send-email-j-keerthy@ti.com>

On Thu, 27 Oct 2016, Keerthy wrote:

> POWERHOLD signal has higher priority  over the DEV_ON bit.
> So power off will not happen if the POWERHOLD is held high.
> Hence reset the MUX to GPIO_7 mode to release the POWERHOLD
> and the DEV_ON bit to take effect to power off the PMIC.
> 
> PMIC Power off happens in dire situations like thermal shutdown
> so irrespective of the POWERHOLD setting go ahead and turn off
> the powerhold.  Currently poweroff is broken on boards that have
> powerhold enabled. This fixes poweroff on those boards.
> 
> Signed-off-by: Keerthy <j-keerthy@ti.com>
> ---
>  drivers/mfd/palmas.c | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
> 
> diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c
> index 8f8bacb..8fbc5e0 100644
> --- a/drivers/mfd/palmas.c
> +++ b/drivers/mfd/palmas.c
> @@ -430,10 +430,28 @@ static void palmas_power_off(void)
>  {
>  	unsigned int addr;
>  	int ret, slave;
> +	struct device_node *node;
> +	bool override_powerhold;
>  
>  	if (!palmas_dev)

Can this happen?

>  		return;
>  
> +	node = palmas_dev->dev->of_node;

Just do:

struct device_node *np = palmas_dev->dev->of_node;

> +	override_powerhold = of_property_read_bool(node,
> +					"ti,palmas-override-powerhold");

Break the line after the '=' instead.

> +	if (override_powerhold) {

if (of_property_read_bool(node,	"ti,palmas-override-powerhold"))

Then remove 'override_powerhold'.

> +		addr = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE,
> +					  PALMAS_PRIMARY_SECONDARY_PAD2);
> +		slave = PALMAS_BASE_TO_SLAVE(PALMAS_PU_PD_OD_BASE);
> +
> +		ret = regmap_update_bits(palmas_dev->regmap[slave], addr,
> +					 PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_7_MASK, 0);
> +		if (ret)
> +			pr_err("%s: Unable to write PALMAS_PRIMARY_SECONDARY_PAD2 %d\n",
> +			       __func__, ret);

Don't use __func__ in live code.

And use dev_err();


> +	}
> +
>  	slave = PALMAS_BASE_TO_SLAVE(PALMAS_PMU_CONTROL_BASE);
>  	addr = PALMAS_BASE_TO_REG(PALMAS_PMU_CONTROL_BASE, PALMAS_DEV_CTRL);
>  

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply


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.