Merge branches 'tz1090_8250_tolerance', 'tz1090_clk_specified', 'tz1090_clks' (early part), 'tz1090_metag' (early part) and 'img_wdt_fixes' into tmp
$ git merge tz1090_8250_tolerance tz1090_clk_specified tz1090_clks~2 tz1090_metag~ img_wdt_fixes
diff --git a/Documentation/devicetree/bindings/clock/specified-clock.txt b/Documentation/devicetree/bindings/clock/specified-clock.txt
new file mode 100644
index 0000000..7135adda
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/specified-clock.txt
@@ -0,0 +1,62 @@
+Binding for discoverable-fixed-rate clock sources.
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be "specified-clock".
+- #clock-cells : from common clock binding; shall be set to 0.
+- bit-mask : Mask of bits in the field specifying the frequency.
+- table : array of integer pairs defining register field values and
+ corresponding clock frequencies in Hz.
+
+Optional properties:
+- reg : Base address of configuration register specifying the frequency.
+- syscon-reg : Phandle to syscon node and offset of syscon register.
+- bit-shift : Number of bits to shift the masked register value.
+ Defaults to (ffs(bit-mask) - 1) if absent.
+- clock-accuracy : accuracy of clock in ppb (parts per billion).
+ Should be a single cell.
+- clock-output-names : From common clock binding.
+
+NOTE: One of reg or syscon-reg must be provided.
+
+Examples:
+ clock {
+ compatible = "specified-clock";
+ #clock-cells = <0>;
+ reg = <0x02004004 0x4>; /* CR_PERIP_RESET_CFG */
+ bit-mask = <0x00000f00>; /* FXTAL */
+ table = /* FXTAL Frequency */
+ <0 16384000>,
+ <1 19200000>,
+ <2 24000000>,
+ <3 24576000>,
+ <4 26000000>,
+ <5 36000000>,
+ <6 36864000>,
+ <7 38400000>,
+ <8 40000000>;
+ clock-accuracy = <100>;
+ clock-output-names = "xtal1";
+ };
+
+ clock {
+ compatible = "specified-clock";
+ #clock-cells = <0>;
+ syscon-reg = <&perip_cr 0x4>; /* CR_PERIP_RESET_CFG */
+ bit-mask = <0x00000f00>; /* FXTAL */
+ table = /* FXTAL Frequency */
+ <0 16384000>,
+ <1 19200000>,
+ <2 24000000>,
+ <3 24576000>,
+ <4 26000000>,
+ <5 36000000>,
+ <6 36864000>,
+ <7 38400000>,
+ <8 40000000>;
+ clock-accuracy = <100>;
+ clock-output-names = "xtal1";
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index 0e1abe8..d13e453 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6379,6 +6379,13 @@
F: drivers/irqchip/irq-metag-ext.c
F: drivers/tty/metag_da.c
+METAG/TZ1090 SOC SUPPORT
+M: James Hogan <james.hogan@imgtec.com>
+L: linux-metag@vger.kernel.org
+S: Maintained
+F: drivers/irqchip/irq-imgpdc.c
+N: tz1090
+
MICROBLAZE ARCHITECTURE
M: Michal Simek <monstr@monstr.eu>
W: http://www.monstr.eu/fdt/
diff --git a/arch/metag/Kconfig b/arch/metag/Kconfig
index 0b389a8..2f72e65 100644
--- a/arch/metag/Kconfig
+++ b/arch/metag/Kconfig
@@ -219,15 +219,42 @@
menu "Boot options"
-config METAG_BUILTIN_DTB
- bool "Embed DTB in kernel image"
- default y
+choice METAG_BUILTIN_DTB
+ prompt "Embed DTB in kernel image"
+ default METAG_BUILTIN_DTB_TZ1090_MINIMORPH if SOC_TZ1090
+ default METAG_BUILTIN_DTB_SKELETON
help
Embeds a device tree binary in the kernel image.
+config METAG_BUILTIN_DTB_NONE
+ bool "None"
+
+config METAG_BUILTIN_DTB_SKELETON
+ bool "Meta Generic"
+
+config METAG_BUILTIN_DTB_TZ1090_GENERIC
+ bool "TZ1090 Generic"
+ depends on SOC_TZ1090
+
+config METAG_BUILTIN_DTB_TZ1090_MINIMORPH
+ bool "TZ1090 01TT - Minimorph Dev Board"
+ depends on SOC_TZ1090
+
+config METAG_BUILTIN_DTB_CUSTOM
+ bool "Custom"
+
+endchoice
+
+config METAG_BUILTIN_DTB
+ def_bool !METAG_BUILTIN_DTB_NONE
+
config METAG_BUILTIN_DTB_NAME
- string "Built in DTB"
+ string "Custom built in DTB" if METAG_BUILTIN_DTB_CUSTOM
depends on METAG_BUILTIN_DTB
+ default "tz1090_generic" if METAG_BUILTIN_DTB_TZ1090_GENERIC
+ default "tz1090_01tt" if METAG_BUILTIN_DTB_TZ1090_MINIMORPH
+ default "tz1090_generic" if SOC_TZ1090
+ default "skeleton"
help
Set the name of the DTB to embed (leave blank to pick one
automatically based on kernel configuration).
diff --git a/arch/metag/Kconfig.soc b/arch/metag/Kconfig.soc
index 973640f..93c21c3 100644
--- a/arch/metag/Kconfig.soc
+++ b/arch/metag/Kconfig.soc
@@ -17,6 +17,7 @@
config SOC_TZ1090
bool "Toumaz Xenif TZ1090 SoC (Comet)"
select ARCH_WANT_OPTIONAL_GPIOLIB
+ select COMMON_CLK
select IMGPDC_IRQ
select METAG_LNKGET_AROUND_CACHE
select METAG_META21
diff --git a/arch/metag/boot/dts/Makefile b/arch/metag/boot/dts/Makefile
index 72c1218..0986fc1 100644
--- a/arch/metag/boot/dts/Makefile
+++ b/arch/metag/boot/dts/Makefile
@@ -1,13 +1,9 @@
dtb-y += skeleton.dtb
dtb-y += tz1090_generic.dtb
+dtb-y += tz1090_01tt.dtb
# Built-in dtb
-builtindtb-y := skeleton
-builtindtb-$(CONFIG_SOC_TZ1090) := tz1090_generic
-
-ifneq ($(CONFIG_METAG_BUILTIN_DTB_NAME),"")
- builtindtb-y := $(patsubst "%",%,$(CONFIG_METAG_BUILTIN_DTB_NAME))
-endif
+builtindtb-y := $(patsubst "%",%,$(CONFIG_METAG_BUILTIN_DTB_NAME))
dtb-$(CONFIG_METAG_BUILTIN_DTB) += $(builtindtb-y).dtb
obj-$(CONFIG_METAG_BUILTIN_DTB) += $(builtindtb-y).dtb.o
diff --git a/arch/metag/boot/dts/tz1090.dtsi b/arch/metag/boot/dts/tz1090.dtsi
index 24ea7d2..5310045 100644
--- a/arch/metag/boot/dts/tz1090.dtsi
+++ b/arch/metag/boot/dts/tz1090.dtsi
@@ -9,12 +9,22 @@
#include "skeleton.dtsi"
#include <dt-bindings/interrupt-controller/irq.h>
+#include "tz1090_clk.dtsi"
/ {
compatible = "toumaz,tz1090", "img,meta";
interrupt-parent = <&intc>;
+ clocks = <&top_cr CLK_TOP_META>;
+ clock-names = "core";
+
+ aliases {
+ i2c0 = &i2c0;
+ i2c1 = &i2c1;
+ i2c2 = &i2c2;
+ };
+
intc: interrupt-controller {
compatible = "img,meta-intc";
interrupt-controller;
@@ -48,6 +58,46 @@
#gpio-range-cells = <3>;
compatible = "img,tz1090-pinctrl";
reg = <0x02005800 0xe4>;
+
+ /* common pin configurations */
+ pinctrl_scb0: scb0 {
+ scb0_cfg {
+ tz1090,pins = "scb0";
+ tz1090,function = "perip";
+ };
+ };
+ pinctrl_scb1: scb1 {
+ scb1_cfg {
+ tz1090,pins = "scb1";
+ tz1090,function = "perip";
+ };
+ };
+ pinctrl_scb2: scb2 {
+ scb2_cfg {
+ tz1090,pins = "scb2";
+ tz1090,function = "perip";
+ };
+ };
+ pinctrl_uart0: uart0 {
+ uart0_cfg {
+ tz1090,pins = "uart0_rxd",
+ "uart0_txd";
+ tz1090,function = "perip";
+ };
+ };
+ pinctrl_uart0_flow: uart0_flow {
+ uart0_cfg {
+ tz1090,pins = "uart0_cts",
+ "uart0_rts";
+ tz1090,function = "perip";
+ };
+ };
+ pinctrl_uart1: uart1 {
+ uart1_cfg {
+ tz1090,pins = "uart1";
+ tz1090,function = "perip";
+ };
+ };
};
pdc_pinctrl: pinctrl@02006500 {
@@ -104,5 +154,96 @@
<10 IRQ_TYPE_NONE>;
gpio-ranges = <&pdc_pinctrl 0 0 7>;
};
+
+ wdt: wdt@02006000 {
+ compatible = "img,pdc-wdt";
+ reg = <0x02006000 0x20>;
+ interrupt-parent = <&pdc>;
+ interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pdc_cr CLK_PDC_32KHZ>,
+ <&top_cr CLK_TOP_PDC>;
+ clock-names = "wdt", "sys";
+ };
+
+ ir: ir@02006200 {
+ compatible = "img,ir-rev1";
+ reg = <0x02006200 0x100>;
+ interrupt-parent = <&pdc>;
+ interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pdc_cr CLK_PDC_32KHZ>,
+ <&pdc_cr CLK_PDC_32KHZ>,
+ <&top_cr CLK_TOP_PDC>;
+ clock-names = "core", "mod", "sys";
+ status = "disabled";
+ };
+
+ i2c0: i2c@02004400 {
+ compatible = "img,scb-i2c";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_scb0>;
+ reg = <0x02004400 0x200>;
+ interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&top_cr CLK_TOP_SCB>,
+ <&perip_cr CLK_PERIP_SCB0>;
+ clock-names = "scb", "sys";
+ status = "disabled";
+ };
+
+ i2c1: i2c@02004600 {
+ compatible = "img,scb-i2c";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_scb1>;
+ reg = <0x02004600 0x200>;
+ interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&top_cr CLK_TOP_SCB>,
+ <&perip_cr CLK_PERIP_SCB1>;
+ clock-names = "scb", "sys";
+ status = "disabled";
+ };
+
+ i2c2: i2c@02004800 {
+ compatible = "img,scb-i2c";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_scb2>;
+ reg = <0x02004800 0x200>;
+ interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&top_cr CLK_TOP_SCB>,
+ <&perip_cr CLK_PERIP_SCB2>;
+ clock-names = "scb", "sys";
+ status = "disabled";
+ };
+
+ uart0: uart@02004b00 {
+ compatible = "snps,dw-apb-uart";
+ pinctrl-names = "default";
+ pinctrl-0 = < &pinctrl_uart0>;
+ reg = <0x02004b00 0x100>;
+ interrupts = <4 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&top_cr CLK_TOP_UART>,
+ <&perip_cr CLK_PERIP_UART0>;
+ clock-names = "baudclk", "apb_pclk";
+ assigned-clocks = <&top_cr CLK_TOP_UART>;
+ assigned-clock-rates = <1843200>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ status = "disabled";
+ };
+
+ uart1: uart@02004c00 {
+ compatible = "snps,dw-apb-uart";
+ pinctrl-names = "default";
+ pinctrl-0 = < &pinctrl_uart1>;
+ reg = <0x02004c00 0x100>;
+ interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&top_cr CLK_TOP_UART>,
+ <&perip_cr CLK_PERIP_UART1>;
+ clock-names = "baudclk", "apb_pclk";
+ assigned-clocks = <&top_cr CLK_TOP_UART>;
+ assigned-clock-rates = <1843200>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ status = "disabled";
+ };
+
};
};
diff --git a/arch/metag/boot/dts/tz1090_01tt.dts b/arch/metag/boot/dts/tz1090_01tt.dts
new file mode 100644
index 0000000..656a71a
--- /dev/null
+++ b/arch/metag/boot/dts/tz1090_01tt.dts
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "tz1090.dtsi"
+
+&xtal2 {
+ clock-frequency = <12000000>;
+};
+
+&xtal3 {
+ clock-frequency = <32768>;
+};
+
+&ir {
+ status = "okay";
+};
+
+&i2c2 {
+ clock-frequency = <100000>; /* limit for HDMI */
+ status = "okay";
+};
+
+&uart0 {
+ status = "okay";
+};
+
+/ {
+ model = "ImgTec 01TT Minimorph";
+ compatible = "img,tz1090-01tt", "img,tz1090-01sp",
+ "toumaz,tz1090", "img,meta";
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <>;
+ softled1 {
+ label = "softled1";
+ gpios = <&gpios0 23 0>; /* uart0_rts */
+ linux,default-trigger = "rc-feedback";
+ };
+ softled2 {
+ label = "softled2";
+ gpios = <&gpios0 11 0>; /* spi0_cs2 */
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+};
diff --git a/arch/metag/boot/dts/tz1090_clk.dtsi b/arch/metag/boot/dts/tz1090_clk.dtsi
new file mode 100644
index 0000000..c86d06e
--- /dev/null
+++ b/arch/metag/boot/dts/tz1090_clk.dtsi
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/clock/tz1090-top.h>
+#include <dt-bindings/clock/tz1090-hep.h>
+#include <dt-bindings/clock/tz1090-perip.h>
+#include <dt-bindings/clock/tz1090-pdc.h>
+
+/ {
+ soc {
+ /*
+ * ============ EXTERNAL CLOCKS/OSCILLATORS ============
+ */
+
+ /* XTAL1 frequency is specified in reset bootstrap config */
+ xtal1: xtal1 {
+ compatible = "specified-clock";
+ #clock-cells = <0>;
+ syscon-reg = <&perip_cr 0x4>; /* CR_PERIP_RESET_CFG */
+ bit-mask = <0x00000f00>; /* FXTAL */
+ /* FXTAL Frequency */
+ table = <0 16384000>,
+ <1 19200000>,
+ <2 24000000>,
+ <3 24576000>,
+ <4 26000000>,
+ <5 36000000>,
+ <6 36864000>,
+ <7 38400000>,
+ <8 40000000>,
+ <9 48000000>;
+ clock-output-names = "xtal1";
+ };
+
+ /* XTAL2 oscillator (board specific, but 12MHz recommended) */
+ xtal2: xtal2 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "xtal2";
+ };
+
+ /* XTAL3 oscillator (32.768KHz if fitted, assume not fitted) */
+ xtal3: xtal3 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "xtal3";
+ };
+
+ ext_adc_dac: ext_adc_dac {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "ext_adc_dac";
+ };
+
+
+ /*
+ * ============ POWERDOWN CONTROLLER CLOCKS ============
+ */
+
+ pdc_cr: pdc_cr {
+ compatible = "img,tz1090-pdc-cr", "syscon";
+ #clock-cells = <1>;
+ reg = <0x02006500 0x4>; /* SOC_GPIO_CONTROL0 */
+ clocks = <&xtal1>,
+ <&xtal3>;
+ clock-names = "xtal1",
+ "xtal3";
+ };
+
+
+ /*
+ * ============ AFE CLOCKS ============
+ */
+
+ afe_clks: afe_clks {
+ /* This is just a placeholder at the moment */
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
+
+ /*
+ * ============ TOP LEVEL CLOCKS ============
+ */
+
+ top_cr: top_cr {
+ compatible = "img,tz1090-top-cr", "syscon";
+ #clock-cells = <1>;
+ reg = <0x02005900 0xb0>;
+ clocks = <&xtal1>, <&xtal2>, <&ext_adc_dac>,
+ <&hep_cr CLK_HEP_DDR_EN>,
+ <&afe_clks>, <&afe_clks>,
+ <&afe_clks>, <&afe_clks>, <&afe_clks>;
+ clock-names = "xtal1", "xtal2", "ext_adc_dac",
+ "ddr_en",
+ "afe_progdiv1", "afe_progdiv3",
+ "afe_rxsync", "afe_txsync", "iqadc_sync";
+ clock-indices = <CLK_TOP_SYS>,
+ <CLK_TOP_SYS_X2_UNDELETED>;
+ clock-output-names = "sys",
+ "sys_x2_undeleted";
+ };
+
+
+ /*
+ * ============ HIGH LEVEL PERIPHERAL CLOCKS ============
+ */
+
+ hep_cr: hep_cr {
+ compatible = "img,tz1090-hep-cr", "syscon";
+ #clock-cells = <1>;
+ reg = <0x02008c00 0x08>;
+ clocks = <&top_cr CLK_TOP_SYS>,
+ <&top_cr CLK_TOP_SYS_X2_UNDELETED>;
+ clock-names = "sys",
+ "sys_x2_undeleted";
+ clock-indices = <CLK_HEP_DDR_EN>;
+ clock-output-names = "ddr_en";
+ };
+
+ /*
+ * ============ PERIPHERAL CLOCKS ============
+ */
+
+ perip_cr: perip_cr {
+ compatible = "img,tz1090-perip-cr", "syscon";
+ #clock-cells = <1>;
+ reg = <0x02004000 0x18>;
+ clocks = <&top_cr CLK_TOP_SYS>;
+ clock-names = "sys";
+ };
+
+ };
+};
diff --git a/arch/metag/boot/dts/tz1090_generic.dts b/arch/metag/boot/dts/tz1090_generic.dts
index f960909..165458d 100644
--- a/arch/metag/boot/dts/tz1090_generic.dts
+++ b/arch/metag/boot/dts/tz1090_generic.dts
@@ -8,3 +8,7 @@
/dts-v1/;
#include "tz1090.dtsi"
+
+&uart0 {
+ status = "okay";
+};
diff --git a/arch/metag/configs/tz1090_defconfig b/arch/metag/configs/tz1090_defconfig
index 9f9316a..6d8eed1 100644
--- a/arch/metag/configs/tz1090_defconfig
+++ b/arch/metag/configs/tz1090_defconfig
@@ -24,17 +24,41 @@
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=1
CONFIG_BLK_DEV_RAM_SIZE=16384
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
CONFIG_DA_TTY=y
CONFIG_DA_CONSOLE=y
# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_DW=y
# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_IMG=y
CONFIG_GPIOLIB=y
# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_CORE=y
+CONFIG_IMGPDC_WDT=y
+CONFIG_MFD_SYSCON=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_RC_SUPPORT=y
+# CONFIG_RC_DECODERS is not set
+CONFIG_RC_DEVICES=y
+CONFIG_IR_IMG=y
+CONFIG_IR_IMG_NEC=y
+CONFIG_IR_IMG_JVC=y
+CONFIG_IR_IMG_SONY=y
+CONFIG_IR_IMG_SHARP=y
+CONFIG_IR_IMG_SANYO=y
# CONFIG_USB_SUPPORT is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
# CONFIG_DNOTIFY is not set
CONFIG_TMPFS=y
# CONFIG_MISC_FILESYSTEMS is not set
diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c
index 0fc56ab..c76241b 100644
--- a/drivers/clk/clk-fixed-rate.c
+++ b/drivers/clk/clk-fixed-rate.c
@@ -9,12 +9,16 @@
* Fixed rate clock implementation
*/
+#include <linux/bitops.h>
#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/regmap.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/of.h>
+#include <linux/of_address.h>
/*
* DOC: basic fixed-rate clock that cannot gate
@@ -134,4 +138,90 @@
}
EXPORT_SYMBOL_GPL(of_fixed_clk_setup);
CLK_OF_DECLARE(fixed_clk, "fixed-clock", of_fixed_clk_setup);
+
+/**
+ * of_specified_clk_read() - Read the register specifying the clock rate.
+ * @node: Device tree node.
+ * @reg_val: Output pointer to write register value.
+ *
+ * Returns: 0 on success, -errno on failure.
+ */
+static int of_specified_clk_read(struct device_node *node, u32 *reg_val)
+{
+ void __iomem *reg;
+ struct regmap *syscon;
+ int ret;
+ u32 offset;
+
+ /* First try iomapping and reading the configuration register */
+ reg = of_iomap(node, 0);
+ if (reg) {
+ *reg_val = readl(reg);
+ iounmap(reg);
+ return 0;
+ }
+
+ /* Next look for a syscon phandle */
+ syscon = syscon_regmap_lookup_by_phandle(node, "syscon-reg");
+ if (IS_ERR(syscon))
+ return PTR_ERR(syscon);
+
+ /* Get the register offset from the second element */
+ ret = of_property_read_u32_index(node, "syscon-reg", 1, &offset);
+ if (ret)
+ return ret;
+
+ /* Read the register value */
+ return regmap_read(syscon, offset, reg_val);
+}
+
+/**
+ * of_specified_clk_setup() - Setup function for discoverable fixed rate clock.
+ * @node: Device tree node.
+ */
+void of_specified_clk_setup(struct device_node *node)
+{
+ struct clk *clk;
+ const char *clk_name = node->name;
+ u32 shift, mask, rate, reg_val, val;
+ u32 accuracy = 0;
+ struct property *prop;
+ const __be32 *p;
+
+ /* Read the register value specifying the clock rate */
+ if (of_specified_clk_read(node, ®_val))
+ return;
+
+ /* Apply bit-mask */
+ if (of_property_read_u32(node, "bit-mask", &mask))
+ return;
+ reg_val &= mask;
+ /* Apply bit-shift */
+ if (of_property_read_u32(node, "bit-shift", &shift))
+ shift = ffs(mask) - 1;
+ reg_val >>= shift;
+
+ /* Look through the mapping for a matching frequency */
+ of_property_for_each_u32(node, "table", prop, p, val) {
+ p = of_prop_next_u32(prop, p, &rate);
+ if (!p)
+ break;
+ if (val == reg_val)
+ goto found_rate;
+ }
+ /* No match found */
+ return;
+found_rate:
+ of_property_read_u32(node, "clock-accuracy", &accuracy);
+
+ of_property_read_string(node, "clock-output-names", &clk_name);
+
+ clk = clk_register_fixed_rate_with_accuracy(NULL, clk_name, NULL,
+ CLK_IS_ROOT, rate,
+ accuracy);
+ if (!IS_ERR(clk))
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+EXPORT_SYMBOL_GPL(of_specified_clk_setup);
+CLK_OF_DECLARE(specified_clk, "specified-clock", of_specified_clk_setup);
#endif
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index deae122..105d4a9 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -2536,16 +2536,18 @@
struct uart_8250_port *up = up_to_u8250p(port);
unsigned char cval;
unsigned long flags;
- unsigned int baud, quot, frac = 0;
+ unsigned int baud, quot, frac = 0, uartclk_hi;
cval = serial8250_compute_lcr(up, termios->c_cflag);
/*
- * Ask the core to calculate the divisor for us.
+ * Ask the core to calculate the divisor for us, but tolerate some
+ * variance (e.g. if the uartclk is only slightly under 1.8432MHz).
*/
+ uartclk_hi = port->uartclk + port->uartclk / 128;
baud = uart_get_baud_rate(port, termios, old,
port->uartclk / 16 / 0xffff,
- port->uartclk / 16);
+ uartclk_hi / 16);
quot = serial8250_get_divisor(up, baud, &frac);
/*
@@ -3269,15 +3271,16 @@
/* check scratch reg to see if port powered off during system sleep */
if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) {
struct ktermios termios;
- unsigned int baud, quot, frac = 0;
+ unsigned int baud, quot, frac = 0, uartclk_hi;
termios.c_cflag = port->cons->cflag;
if (port->state->port.tty && termios.c_cflag == 0)
termios.c_cflag = port->state->port.tty->termios.c_cflag;
+ uartclk_hi = port->uartclk + port->uartclk / 128;
baud = uart_get_baud_rate(port, &termios, NULL,
port->uartclk / 16 / 0xffff,
- port->uartclk / 16);
+ uartclk_hi / 16);
quot = serial8250_get_divisor(up, baud, &frac);
serial8250_set_divisor(port, baud, quot, frac);
diff --git a/drivers/watchdog/imgpdc_wdt.c b/drivers/watchdog/imgpdc_wdt.c
index c8def68..0deaa4f 100644
--- a/drivers/watchdog/imgpdc_wdt.c
+++ b/drivers/watchdog/imgpdc_wdt.c
@@ -42,10 +42,10 @@
#define PDC_WDT_MIN_TIMEOUT 1
#define PDC_WDT_DEF_TIMEOUT 64
-static int heartbeat;
+static int heartbeat = PDC_WDT_DEF_TIMEOUT;
module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. "
- "(default = " __MODULE_STRING(PDC_WDT_DEF_TIMEOUT) ")");
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds "
+ "(default=" __MODULE_STRING(PDC_WDT_DEF_TIMEOUT) ")");
static bool nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, bool, 0);
@@ -191,6 +191,7 @@
pdc_wdt->wdt_dev.ops = &pdc_wdt_ops;
pdc_wdt->wdt_dev.max_timeout = 1 << PDC_WDT_CONFIG_DELAY_MASK;
pdc_wdt->wdt_dev.parent = &pdev->dev;
+ watchdog_set_drvdata(&pdc_wdt->wdt_dev, pdc_wdt);
ret = watchdog_init_timeout(&pdc_wdt->wdt_dev, heartbeat, &pdev->dev);
if (ret < 0) {
@@ -232,7 +233,6 @@
watchdog_set_nowayout(&pdc_wdt->wdt_dev, nowayout);
platform_set_drvdata(pdev, pdc_wdt);
- watchdog_set_drvdata(&pdc_wdt->wdt_dev, pdc_wdt);
ret = watchdog_register_device(&pdc_wdt->wdt_dev);
if (ret)
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 5591ea7..80e54bf 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -265,6 +265,7 @@
unsigned long fixed_rate, unsigned long fixed_accuracy);
void of_fixed_clk_setup(struct device_node *np);
+void of_specified_clk_setup(struct device_node *np);
/**
* struct clk_gate - gating clock