From: Tomasz Maciej Nowak Date: Sun, 13 Jan 2019 20:30:24 +0000 (+0100) Subject: mvebu: sort armada 37xx upstream patches chronologically X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=b004835908c9aa3f6fe52edfd82269aa9dd04f89;p=openwrt%2Fstaging%2Fluka.git mvebu: sort armada 37xx upstream patches chronologically Signed-off-by: Tomasz Maciej Nowak --- diff --git a/target/linux/mvebu/patches-4.14/500-arm64-dts-marvell-Fix-A37xx-UART0-register-size.patch b/target/linux/mvebu/patches-4.14/500-arm64-dts-marvell-Fix-A37xx-UART0-register-size.patch new file mode 100644 index 0000000000..9e2b1c14eb --- /dev/null +++ b/target/linux/mvebu/patches-4.14/500-arm64-dts-marvell-Fix-A37xx-UART0-register-size.patch @@ -0,0 +1,39 @@ +From c737abc193d16e62e23e2fb585b8b7398ab380d8 Mon Sep 17 00:00:00 2001 +From: allen yan +Date: Thu, 7 Sep 2017 15:04:53 +0200 +Subject: arm64: dts: marvell: Fix A37xx UART0 register size + +Armada-37xx UART0 registers are 0x200 bytes wide. Right next to them are +the UART1 registers that should not be declared in this node. + +Update the example in DT bindings document accordingly. + +Signed-off-by: allen yan +Signed-off-by: Miquel Raynal +Signed-off-by: Gregory CLEMENT +--- + Documentation/devicetree/bindings/serial/mvebu-uart.txt | 2 +- + arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/Documentation/devicetree/bindings/serial/mvebu-uart.txt ++++ b/Documentation/devicetree/bindings/serial/mvebu-uart.txt +@@ -8,6 +8,6 @@ Required properties: + Example: + serial@12000 { + compatible = "marvell,armada-3700-uart"; +- reg = <0x12000 0x400>; ++ reg = <0x12000 0x200>; + interrupts = <43>; + }; +--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi ++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi +@@ -134,7 +134,7 @@ + + uart0: serial@12000 { + compatible = "marvell,armada-3700-uart"; +- reg = <0x12000 0x400>; ++ reg = <0x12000 0x200>; + interrupts = ; + status = "disabled"; + }; diff --git a/target/linux/mvebu/patches-4.14/500-clk-mvebu-armada-37xx-periph-cosmetic-changes.patch b/target/linux/mvebu/patches-4.14/500-clk-mvebu-armada-37xx-periph-cosmetic-changes.patch deleted file mode 100644 index 7343e01d19..0000000000 --- a/target/linux/mvebu/patches-4.14/500-clk-mvebu-armada-37xx-periph-cosmetic-changes.patch +++ /dev/null @@ -1,78 +0,0 @@ -From adf4e289dd7f801c3fe12e0e6b491e11e548cd3d Mon Sep 17 00:00:00 2001 -From: Gregory CLEMENT -Date: Thu, 30 Nov 2017 14:40:27 +0100 -Subject: clk: mvebu: armada-37xx-periph: cosmetic changes - -This patches fixes few cosmetic issues such as alignment, blank lines -and required space. - -Signed-off-by: Gregory CLEMENT -Signed-off-by: Stephen Boyd ---- - drivers/clk/mvebu/armada-37xx-periph.c | 17 +++++++++-------- - 1 file changed, 9 insertions(+), 8 deletions(-) - ---- a/drivers/clk/mvebu/armada-37xx-periph.c -+++ b/drivers/clk/mvebu/armada-37xx-periph.c -@@ -79,6 +79,7 @@ static const struct clk_div_table clk_ta - { .val = 1, .div = 4, }, - { .val = 0, .div = 0, }, /* last entry */ - }; -+ - static const struct clk_ops clk_double_div_ops; - - #define PERIPH_GATE(_name, _bit) \ -@@ -217,7 +218,7 @@ PERIPH_CLK_FULL(counter, 23, 20, DIV_SEL - PERIPH_CLK_FULL_DD(eip97, 24, 24, DIV_SEL2, DIV_SEL2, 22, 19); - PERIPH_CLK_MUX_DIV(cpu, 22, DIV_SEL0, 28, clk_table6); - --static struct clk_periph_data data_nb[] ={ -+static struct clk_periph_data data_nb[] = { - REF_CLK_FULL_DD(mmc), - REF_CLK_FULL_DD(sata_host), - REF_CLK_FULL_DD(sec_at), -@@ -281,7 +282,7 @@ static unsigned int get_div(void __iomem - } - - static unsigned long clk_double_div_recalc_rate(struct clk_hw *hw, -- unsigned long parent_rate) -+ unsigned long parent_rate) - { - struct clk_double_div *double_div = to_clk_double_div(hw); - unsigned int div; -@@ -303,6 +304,7 @@ static const struct of_device_id armada_ - .data = data_sb, }, - { } - }; -+ - static int armada_3700_add_composite_clk(const struct clk_periph_data *data, - void __iomem *reg, spinlock_t *lock, - struct device *dev, struct clk_hw **hw) -@@ -355,9 +357,9 @@ static int armada_3700_add_composite_clk - } - - *hw = clk_hw_register_composite(dev, data->name, data->parent_names, -- data->num_parents, mux_hw, -- mux_ops, rate_hw, rate_ops, -- gate_hw, gate_ops, CLK_IGNORE_UNUSED); -+ data->num_parents, mux_hw, -+ mux_ops, rate_hw, rate_ops, -+ gate_hw, gate_ops, CLK_IGNORE_UNUSED); - - if (IS_ERR(*hw)) - return PTR_ERR(*hw); -@@ -406,12 +408,11 @@ static int armada_3700_periph_clock_prob - if (armada_3700_add_composite_clk(&data[i], reg, - &driver_data->lock, dev, hw)) - dev_err(dev, "Can't register periph clock %s\n", -- data[i].name); -- -+ data[i].name); - } - - ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, -- driver_data->hw_data); -+ driver_data->hw_data); - if (ret) { - for (i = 0; i < num_periph; i++) - clk_hw_unregister(driver_data->hw_data->hws[i]); diff --git a/target/linux/mvebu/patches-4.14/501-clk-mvebu-armada-37xx-periph-prepare-cpu-clk-to-be-u.patch b/target/linux/mvebu/patches-4.14/501-clk-mvebu-armada-37xx-periph-prepare-cpu-clk-to-be-u.patch deleted file mode 100644 index f9dec9f2ee..0000000000 --- a/target/linux/mvebu/patches-4.14/501-clk-mvebu-armada-37xx-periph-prepare-cpu-clk-to-be-u.patch +++ /dev/null @@ -1,178 +0,0 @@ -From 9818a7a4fd10f72537cdf2a5ec3402f2c245ea24 Mon Sep 17 00:00:00 2001 -From: Gregory CLEMENT -Date: Thu, 30 Nov 2017 14:40:28 +0100 -Subject: clk: mvebu: armada-37xx-periph: prepare cpu clk to be - used with DVFS - -When DVFS will be enabled then the cpu clk will use a different set of -register at run time. That means that we won't be able to use the common -callback and need to use our own ones. - -This patch prepares this change by switching on our own set of callbacks -without modifying the behavior of the clocks. - -Signed-off-by: Gregory CLEMENT -Signed-off-by: Stephen Boyd ---- - drivers/clk/mvebu/armada-37xx-periph.c | 82 ++++++++++++++++++++++++++++++---- - 1 file changed, 73 insertions(+), 9 deletions(-) - ---- a/drivers/clk/mvebu/armada-37xx-periph.c -+++ b/drivers/clk/mvebu/armada-37xx-periph.c -@@ -46,7 +46,17 @@ struct clk_double_div { - u8 shift2; - }; - -+struct clk_pm_cpu { -+ struct clk_hw hw; -+ void __iomem *reg_mux; -+ u8 shift_mux; -+ u32 mask_mux; -+ void __iomem *reg_div; -+ u8 shift_div; -+}; -+ - #define to_clk_double_div(_hw) container_of(_hw, struct clk_double_div, hw) -+#define to_clk_pm_cpu(_hw) container_of(_hw, struct clk_pm_cpu, hw) - - struct clk_periph_data { - const char *name; -@@ -55,6 +65,7 @@ struct clk_periph_data { - struct clk_hw *mux_hw; - struct clk_hw *rate_hw; - struct clk_hw *gate_hw; -+ struct clk_hw *muxrate_hw; - bool is_double_div; - }; - -@@ -81,6 +92,7 @@ static const struct clk_div_table clk_ta - }; - - static const struct clk_ops clk_double_div_ops; -+static const struct clk_ops clk_pm_cpu_ops; - - #define PERIPH_GATE(_name, _bit) \ - struct clk_gate gate_##_name = { \ -@@ -122,6 +134,18 @@ struct clk_divider rate_##_name = { \ - } \ - }; - -+#define PERIPH_PM_CPU(_name, _shift1, _reg, _shift2) \ -+struct clk_pm_cpu muxrate_##_name = { \ -+ .reg_mux = (void *)TBG_SEL, \ -+ .mask_mux = 3, \ -+ .shift_mux = _shift1, \ -+ .reg_div = (void *)_reg, \ -+ .shift_div = _shift2, \ -+ .hw.init = &(struct clk_init_data){ \ -+ .ops = &clk_pm_cpu_ops, \ -+ } \ -+}; -+ - #define PERIPH_CLK_FULL_DD(_name, _bit, _shift, _reg1, _reg2, _shift1, _shift2)\ - static PERIPH_GATE(_name, _bit); \ - static PERIPH_MUX(_name, _shift); \ -@@ -136,10 +160,6 @@ static PERIPH_DIV(_name, _reg, _shift1, - static PERIPH_GATE(_name, _bit); \ - static PERIPH_DIV(_name, _reg, _shift, _table); - --#define PERIPH_CLK_MUX_DIV(_name, _shift, _reg, _shift_div, _table) \ --static PERIPH_MUX(_name, _shift); \ --static PERIPH_DIV(_name, _reg, _shift_div, _table); -- - #define PERIPH_CLK_MUX_DD(_name, _shift, _reg1, _reg2, _shift1, _shift2)\ - static PERIPH_MUX(_name, _shift); \ - static PERIPH_DOUBLEDIV(_name, _reg1, _reg2, _shift1, _shift2); -@@ -180,13 +200,12 @@ static PERIPH_DOUBLEDIV(_name, _reg1, _r - .rate_hw = &rate_##_name.hw, \ - } - --#define REF_CLK_MUX_DIV(_name) \ -+#define REF_CLK_PM_CPU(_name) \ - { .name = #_name, \ - .parent_names = (const char *[]){ "TBG-A-P", \ - "TBG-B-P", "TBG-A-S", "TBG-B-S"}, \ - .num_parents = 4, \ -- .mux_hw = &mux_##_name.hw, \ -- .rate_hw = &rate_##_name.hw, \ -+ .muxrate_hw = &muxrate_##_name.hw, \ - } - - #define REF_CLK_MUX_DD(_name) \ -@@ -216,7 +235,7 @@ PERIPH_CLK_FULL_DD(ddr_fclk, 21, 16, DIV - PERIPH_CLK_FULL(trace, 22, 18, DIV_SEL0, 20, clk_table6); - PERIPH_CLK_FULL(counter, 23, 20, DIV_SEL0, 23, clk_table6); - PERIPH_CLK_FULL_DD(eip97, 24, 24, DIV_SEL2, DIV_SEL2, 22, 19); --PERIPH_CLK_MUX_DIV(cpu, 22, DIV_SEL0, 28, clk_table6); -+static PERIPH_PM_CPU(cpu, 22, DIV_SEL0, 28); - - static struct clk_periph_data data_nb[] = { - REF_CLK_FULL_DD(mmc), -@@ -235,7 +254,7 @@ static struct clk_periph_data data_nb[] - REF_CLK_FULL(trace), - REF_CLK_FULL(counter), - REF_CLK_FULL_DD(eip97), -- REF_CLK_MUX_DIV(cpu), -+ REF_CLK_PM_CPU(cpu), - { }, - }; - -@@ -297,6 +316,37 @@ static const struct clk_ops clk_double_d - .recalc_rate = clk_double_div_recalc_rate, - }; - -+static u8 clk_pm_cpu_get_parent(struct clk_hw *hw) -+{ -+ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); -+ int num_parents = clk_hw_get_num_parents(hw); -+ u32 val; -+ -+ val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux; -+ val &= pm_cpu->mask_mux; -+ -+ if (val >= num_parents) -+ return -EINVAL; -+ -+ return val; -+} -+ -+static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); -+ unsigned int div; -+ -+ div = get_div(pm_cpu->reg_div, pm_cpu->shift_div); -+ -+ return DIV_ROUND_UP_ULL((u64)parent_rate, div); -+} -+ -+static const struct clk_ops clk_pm_cpu_ops = { -+ .get_parent = clk_pm_cpu_get_parent, -+ .recalc_rate = clk_pm_cpu_recalc_rate, -+}; -+ - static const struct of_device_id armada_3700_periph_clock_of_match[] = { - { .compatible = "marvell,armada-3700-periph-clock-nb", - .data = data_nb, }, -@@ -356,6 +406,20 @@ static int armada_3700_add_composite_clk - } - } - -+ if (data->muxrate_hw) { -+ struct clk_pm_cpu *pmcpu_clk; -+ struct clk_hw *muxrate_hw = data->muxrate_hw; -+ -+ pmcpu_clk = to_clk_pm_cpu(muxrate_hw); -+ pmcpu_clk->reg_mux = reg + (u64)pmcpu_clk->reg_mux; -+ pmcpu_clk->reg_div = reg + (u64)pmcpu_clk->reg_div; -+ -+ mux_hw = muxrate_hw; -+ rate_hw = muxrate_hw; -+ mux_ops = muxrate_hw->init->ops; -+ rate_ops = muxrate_hw->init->ops; -+ } -+ - *hw = clk_hw_register_composite(dev, data->name, data->parent_names, - data->num_parents, mux_hw, - mux_ops, rate_hw, rate_ops, diff --git a/target/linux/mvebu/patches-4.14/501-spi-a3700-Change-SPI-mode-before-asserting-chip-sele.patch b/target/linux/mvebu/patches-4.14/501-spi-a3700-Change-SPI-mode-before-asserting-chip-sele.patch new file mode 100644 index 0000000000..3ac7091188 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/501-spi-a3700-Change-SPI-mode-before-asserting-chip-sele.patch @@ -0,0 +1,70 @@ +From dd7aa8d4b53b3484ba31ba56f3ff1be7deb38530 Mon Sep 17 00:00:00 2001 +From: Maxime Chevallier +Date: Tue, 10 Oct 2017 10:43:18 +0200 +Subject: spi: a3700: Change SPI mode before asserting chip-select + +The spi device mode should be configured in the controller before the +chip-select is asserted, so that a clock polarity configuration change +is not interpreted as a clock tick by the device. + +This patch moves the mode setting to the 'prepare_message' function +instead of the 'transfer_one' function. + +By doing so, this patch also removes redundant code in +a3700_spi_clock_set. + +This was tested on EspressoBin board, with spidev. + +Signed-off-by: Maxime Chevallier +Signed-off-by: Mark Brown +--- + drivers/spi/spi-armada-3700.c | 17 ++++------------- + 1 file changed, 4 insertions(+), 13 deletions(-) + +--- a/drivers/spi/spi-armada-3700.c ++++ b/drivers/spi/spi-armada-3700.c +@@ -214,7 +214,7 @@ static void a3700_spi_mode_set(struct a3 + } + + static void a3700_spi_clock_set(struct a3700_spi *a3700_spi, +- unsigned int speed_hz, u16 mode) ++ unsigned int speed_hz) + { + u32 val; + u32 prescale; +@@ -239,17 +239,6 @@ static void a3700_spi_clock_set(struct a + val |= A3700_SPI_CLK_CAPT_EDGE; + spireg_write(a3700_spi, A3700_SPI_IF_TIME_REG, val); + } +- +- val = spireg_read(a3700_spi, A3700_SPI_IF_CFG_REG); +- val &= ~(A3700_SPI_CLK_POL | A3700_SPI_CLK_PHA); +- +- if (mode & SPI_CPOL) +- val |= A3700_SPI_CLK_POL; +- +- if (mode & SPI_CPHA) +- val |= A3700_SPI_CLK_PHA; +- +- spireg_write(a3700_spi, A3700_SPI_IF_CFG_REG, val); + } + + static void a3700_spi_bytelen_set(struct a3700_spi *a3700_spi, unsigned int len) +@@ -431,7 +420,7 @@ static void a3700_spi_transfer_setup(str + + a3700_spi = spi_master_get_devdata(spi->master); + +- a3700_spi_clock_set(a3700_spi, xfer->speed_hz, spi->mode); ++ a3700_spi_clock_set(a3700_spi, xfer->speed_hz); + + byte_len = xfer->bits_per_word >> 3; + +@@ -592,6 +581,8 @@ static int a3700_spi_prepare_message(str + + a3700_spi_bytelen_set(a3700_spi, 4); + ++ a3700_spi_mode_set(a3700_spi, spi->mode); ++ + return 0; + } + diff --git a/target/linux/mvebu/patches-4.14/502-arm64-dts-marvell-armada-37xx-add-UART-clock.patch b/target/linux/mvebu/patches-4.14/502-arm64-dts-marvell-armada-37xx-add-UART-clock.patch new file mode 100644 index 0000000000..47e0751c5f --- /dev/null +++ b/target/linux/mvebu/patches-4.14/502-arm64-dts-marvell-armada-37xx-add-UART-clock.patch @@ -0,0 +1,27 @@ +From 2ff0d0b5bb397c3dc5c9b97bd0f20948f0b77740 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Fri, 13 Oct 2017 11:01:57 +0200 +Subject: arm64: dts: marvell: armada-37xx: add UART clock + +Add the missing clock property to armada-3700 UART node. + +This clock will be used to derive the prescaler value to comply with +the requested baudrate. + +Signed-off-by: Miquel Raynal +Acked-by: Gregory CLEMENT +Signed-off-by: Gregory CLEMENT +--- + arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi ++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi +@@ -135,6 +135,7 @@ + uart0: serial@12000 { + compatible = "marvell,armada-3700-uart"; + reg = <0x12000 0x200>; ++ clocks = <&xtalclk>; + interrupts = ; + status = "disabled"; + }; diff --git a/target/linux/mvebu/patches-4.14/502-clk-mvebu-armada-37xx-periph-add-DVFS-support-for-cp.patch b/target/linux/mvebu/patches-4.14/502-clk-mvebu-armada-37xx-periph-add-DVFS-support-for-cp.patch deleted file mode 100644 index 2065e788af..0000000000 --- a/target/linux/mvebu/patches-4.14/502-clk-mvebu-armada-37xx-periph-add-DVFS-support-for-cp.patch +++ /dev/null @@ -1,315 +0,0 @@ -From 2089dc33ea0e3917465929d4020fbff3d6dbf7f4 Mon Sep 17 00:00:00 2001 -From: Gregory CLEMENT -Date: Thu, 30 Nov 2017 14:40:29 +0100 -Subject: clk: mvebu: armada-37xx-periph: add DVFS support for cpu clocks - -When DVFS is enabled the CPU clock setting is done using an other set of -registers. - -These Power Management registers are exposed through a syscon as they -will also be used by other drivers such as the cpufreq. - -This patch add the possibility to modify the CPU frequency using the -associate load level matching the target frequency. Then all the -frequency switch is handle by the hardware. - -Signed-off-by: Gregory CLEMENT -[sboyd@codeaurora.org: Grow a local variable for regmap pointer -to keep lines shorter] -Signed-off-by: Stephen Boyd ---- - drivers/clk/mvebu/armada-37xx-periph.c | 221 ++++++++++++++++++++++++++++++++- - 1 file changed, 217 insertions(+), 4 deletions(-) - ---- a/drivers/clk/mvebu/armada-37xx-periph.c -+++ b/drivers/clk/mvebu/armada-37xx-periph.c -@@ -21,9 +21,11 @@ - */ - - #include -+#include - #include - #include - #include -+#include - #include - - #define TBG_SEL 0x0 -@@ -33,6 +35,26 @@ - #define CLK_SEL 0x10 - #define CLK_DIS 0x14 - -+#define LOAD_LEVEL_NR 4 -+ -+#define ARMADA_37XX_NB_L0L1 0x18 -+#define ARMADA_37XX_NB_L2L3 0x1C -+#define ARMADA_37XX_NB_TBG_DIV_OFF 13 -+#define ARMADA_37XX_NB_TBG_DIV_MASK 0x7 -+#define ARMADA_37XX_NB_CLK_SEL_OFF 11 -+#define ARMADA_37XX_NB_CLK_SEL_MASK 0x1 -+#define ARMADA_37XX_NB_TBG_SEL_OFF 9 -+#define ARMADA_37XX_NB_TBG_SEL_MASK 0x3 -+#define ARMADA_37XX_NB_CONFIG_SHIFT 16 -+#define ARMADA_37XX_NB_DYN_MOD 0x24 -+#define ARMADA_37XX_NB_DFS_EN 31 -+#define ARMADA_37XX_NB_CPU_LOAD 0x30 -+#define ARMADA_37XX_NB_CPU_LOAD_MASK 0x3 -+#define ARMADA_37XX_DVFS_LOAD_0 0 -+#define ARMADA_37XX_DVFS_LOAD_1 1 -+#define ARMADA_37XX_DVFS_LOAD_2 2 -+#define ARMADA_37XX_DVFS_LOAD_3 3 -+ - struct clk_periph_driver_data { - struct clk_hw_onecell_data *hw_data; - spinlock_t lock; -@@ -53,6 +75,7 @@ struct clk_pm_cpu { - u32 mask_mux; - void __iomem *reg_div; - u8 shift_div; -+ struct regmap *nb_pm_base; - }; - - #define to_clk_double_div(_hw) container_of(_hw, struct clk_double_div, hw) -@@ -316,14 +339,94 @@ static const struct clk_ops clk_double_d - .recalc_rate = clk_double_div_recalc_rate, - }; - -+static void armada_3700_pm_dvfs_update_regs(unsigned int load_level, -+ unsigned int *reg, -+ unsigned int *offset) -+{ -+ if (load_level <= ARMADA_37XX_DVFS_LOAD_1) -+ *reg = ARMADA_37XX_NB_L0L1; -+ else -+ *reg = ARMADA_37XX_NB_L2L3; -+ -+ if (load_level == ARMADA_37XX_DVFS_LOAD_0 || -+ load_level == ARMADA_37XX_DVFS_LOAD_2) -+ *offset += ARMADA_37XX_NB_CONFIG_SHIFT; -+} -+ -+static bool armada_3700_pm_dvfs_is_enabled(struct regmap *base) -+{ -+ unsigned int val, reg = ARMADA_37XX_NB_DYN_MOD; -+ -+ if (IS_ERR(base)) -+ return false; -+ -+ regmap_read(base, reg, &val); -+ -+ return !!(val & BIT(ARMADA_37XX_NB_DFS_EN)); -+} -+ -+static unsigned int armada_3700_pm_dvfs_get_cpu_div(struct regmap *base) -+{ -+ unsigned int reg = ARMADA_37XX_NB_CPU_LOAD; -+ unsigned int offset = ARMADA_37XX_NB_TBG_DIV_OFF; -+ unsigned int load_level, div; -+ -+ /* -+ * This function is always called after the function -+ * armada_3700_pm_dvfs_is_enabled, so no need to check again -+ * if the base is valid. -+ */ -+ regmap_read(base, reg, &load_level); -+ -+ /* -+ * The register and the offset inside this register accessed to -+ * read the current divider depend on the load level -+ */ -+ load_level &= ARMADA_37XX_NB_CPU_LOAD_MASK; -+ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset); -+ -+ regmap_read(base, reg, &div); -+ -+ return (div >> offset) & ARMADA_37XX_NB_TBG_DIV_MASK; -+} -+ -+static unsigned int armada_3700_pm_dvfs_get_cpu_parent(struct regmap *base) -+{ -+ unsigned int reg = ARMADA_37XX_NB_CPU_LOAD; -+ unsigned int offset = ARMADA_37XX_NB_TBG_SEL_OFF; -+ unsigned int load_level, sel; -+ -+ /* -+ * This function is always called after the function -+ * armada_3700_pm_dvfs_is_enabled, so no need to check again -+ * if the base is valid -+ */ -+ regmap_read(base, reg, &load_level); -+ -+ /* -+ * The register and the offset inside this register accessed to -+ * read the current divider depend on the load level -+ */ -+ load_level &= ARMADA_37XX_NB_CPU_LOAD_MASK; -+ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset); -+ -+ regmap_read(base, reg, &sel); -+ -+ return (sel >> offset) & ARMADA_37XX_NB_TBG_SEL_MASK; -+} -+ - static u8 clk_pm_cpu_get_parent(struct clk_hw *hw) - { - struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); - int num_parents = clk_hw_get_num_parents(hw); - u32 val; - -- val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux; -- val &= pm_cpu->mask_mux; -+ if (armada_3700_pm_dvfs_is_enabled(pm_cpu->nb_pm_base)) { -+ val = armada_3700_pm_dvfs_get_cpu_parent(pm_cpu->nb_pm_base); -+ } else { -+ val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux; -+ val &= pm_cpu->mask_mux; -+ } - - if (val >= num_parents) - return -EINVAL; -@@ -331,19 +434,124 @@ static u8 clk_pm_cpu_get_parent(struct c - return val; - } - -+static int clk_pm_cpu_set_parent(struct clk_hw *hw, u8 index) -+{ -+ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); -+ struct regmap *base = pm_cpu->nb_pm_base; -+ int load_level; -+ -+ /* -+ * We set the clock parent only if the DVFS is available but -+ * not enabled. -+ */ -+ if (IS_ERR(base) || armada_3700_pm_dvfs_is_enabled(base)) -+ return -EINVAL; -+ -+ /* Set the parent clock for all the load level */ -+ for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) { -+ unsigned int reg, mask, val, -+ offset = ARMADA_37XX_NB_TBG_SEL_OFF; -+ -+ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset); -+ -+ val = index << offset; -+ mask = ARMADA_37XX_NB_TBG_SEL_MASK << offset; -+ regmap_update_bits(base, reg, mask, val); -+ } -+ return 0; -+} -+ - static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) - { - struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); - unsigned int div; - -- div = get_div(pm_cpu->reg_div, pm_cpu->shift_div); -- -+ if (armada_3700_pm_dvfs_is_enabled(pm_cpu->nb_pm_base)) -+ div = armada_3700_pm_dvfs_get_cpu_div(pm_cpu->nb_pm_base); -+ else -+ div = get_div(pm_cpu->reg_div, pm_cpu->shift_div); - return DIV_ROUND_UP_ULL((u64)parent_rate, div); - } - -+static long clk_pm_cpu_round_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long *parent_rate) -+{ -+ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); -+ struct regmap *base = pm_cpu->nb_pm_base; -+ unsigned int div = *parent_rate / rate; -+ unsigned int load_level; -+ /* only available when DVFS is enabled */ -+ if (!armada_3700_pm_dvfs_is_enabled(base)) -+ return -EINVAL; -+ -+ for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) { -+ unsigned int reg, val, offset = ARMADA_37XX_NB_TBG_DIV_OFF; -+ -+ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset); -+ -+ regmap_read(base, reg, &val); -+ -+ val >>= offset; -+ val &= ARMADA_37XX_NB_TBG_DIV_MASK; -+ if (val == div) -+ /* -+ * We found a load level matching the target -+ * divider, switch to this load level and -+ * return. -+ */ -+ return *parent_rate / div; -+ } -+ -+ /* We didn't find any valid divider */ -+ return -EINVAL; -+} -+ -+static int clk_pm_cpu_set_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long parent_rate) -+{ -+ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); -+ struct regmap *base = pm_cpu->nb_pm_base; -+ unsigned int div = parent_rate / rate; -+ unsigned int load_level; -+ -+ /* only available when DVFS is enabled */ -+ if (!armada_3700_pm_dvfs_is_enabled(base)) -+ return -EINVAL; -+ -+ for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) { -+ unsigned int reg, mask, val, -+ offset = ARMADA_37XX_NB_TBG_DIV_OFF; -+ -+ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset); -+ -+ regmap_read(base, reg, &val); -+ val >>= offset; -+ val &= ARMADA_37XX_NB_TBG_DIV_MASK; -+ -+ if (val == div) { -+ /* -+ * We found a load level matching the target -+ * divider, switch to this load level and -+ * return. -+ */ -+ reg = ARMADA_37XX_NB_CPU_LOAD; -+ mask = ARMADA_37XX_NB_CPU_LOAD_MASK; -+ regmap_update_bits(base, reg, mask, load_level); -+ -+ return rate; -+ } -+ } -+ -+ /* We didn't find any valid divider */ -+ return -EINVAL; -+} -+ - static const struct clk_ops clk_pm_cpu_ops = { - .get_parent = clk_pm_cpu_get_parent, -+ .set_parent = clk_pm_cpu_set_parent, -+ .round_rate = clk_pm_cpu_round_rate, -+ .set_rate = clk_pm_cpu_set_rate, - .recalc_rate = clk_pm_cpu_recalc_rate, - }; - -@@ -409,6 +617,7 @@ static int armada_3700_add_composite_clk - if (data->muxrate_hw) { - struct clk_pm_cpu *pmcpu_clk; - struct clk_hw *muxrate_hw = data->muxrate_hw; -+ struct regmap *map; - - pmcpu_clk = to_clk_pm_cpu(muxrate_hw); - pmcpu_clk->reg_mux = reg + (u64)pmcpu_clk->reg_mux; -@@ -418,6 +627,10 @@ static int armada_3700_add_composite_clk - rate_hw = muxrate_hw; - mux_ops = muxrate_hw->init->ops; - rate_ops = muxrate_hw->init->ops; -+ -+ map = syscon_regmap_lookup_by_compatible( -+ "marvell,armada-3700-nb-pm"); -+ pmcpu_clk->nb_pm_base = map; - } - - *hw = clk_hw_register_composite(dev, data->name, data->parent_names, diff --git a/target/linux/mvebu/patches-4.14/503-clk-mvebu-armada-37xx-periph-cosmetic-changes.patch b/target/linux/mvebu/patches-4.14/503-clk-mvebu-armada-37xx-periph-cosmetic-changes.patch new file mode 100644 index 0000000000..7343e01d19 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/503-clk-mvebu-armada-37xx-periph-cosmetic-changes.patch @@ -0,0 +1,78 @@ +From adf4e289dd7f801c3fe12e0e6b491e11e548cd3d Mon Sep 17 00:00:00 2001 +From: Gregory CLEMENT +Date: Thu, 30 Nov 2017 14:40:27 +0100 +Subject: clk: mvebu: armada-37xx-periph: cosmetic changes + +This patches fixes few cosmetic issues such as alignment, blank lines +and required space. + +Signed-off-by: Gregory CLEMENT +Signed-off-by: Stephen Boyd +--- + drivers/clk/mvebu/armada-37xx-periph.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +--- a/drivers/clk/mvebu/armada-37xx-periph.c ++++ b/drivers/clk/mvebu/armada-37xx-periph.c +@@ -79,6 +79,7 @@ static const struct clk_div_table clk_ta + { .val = 1, .div = 4, }, + { .val = 0, .div = 0, }, /* last entry */ + }; ++ + static const struct clk_ops clk_double_div_ops; + + #define PERIPH_GATE(_name, _bit) \ +@@ -217,7 +218,7 @@ PERIPH_CLK_FULL(counter, 23, 20, DIV_SEL + PERIPH_CLK_FULL_DD(eip97, 24, 24, DIV_SEL2, DIV_SEL2, 22, 19); + PERIPH_CLK_MUX_DIV(cpu, 22, DIV_SEL0, 28, clk_table6); + +-static struct clk_periph_data data_nb[] ={ ++static struct clk_periph_data data_nb[] = { + REF_CLK_FULL_DD(mmc), + REF_CLK_FULL_DD(sata_host), + REF_CLK_FULL_DD(sec_at), +@@ -281,7 +282,7 @@ static unsigned int get_div(void __iomem + } + + static unsigned long clk_double_div_recalc_rate(struct clk_hw *hw, +- unsigned long parent_rate) ++ unsigned long parent_rate) + { + struct clk_double_div *double_div = to_clk_double_div(hw); + unsigned int div; +@@ -303,6 +304,7 @@ static const struct of_device_id armada_ + .data = data_sb, }, + { } + }; ++ + static int armada_3700_add_composite_clk(const struct clk_periph_data *data, + void __iomem *reg, spinlock_t *lock, + struct device *dev, struct clk_hw **hw) +@@ -355,9 +357,9 @@ static int armada_3700_add_composite_clk + } + + *hw = clk_hw_register_composite(dev, data->name, data->parent_names, +- data->num_parents, mux_hw, +- mux_ops, rate_hw, rate_ops, +- gate_hw, gate_ops, CLK_IGNORE_UNUSED); ++ data->num_parents, mux_hw, ++ mux_ops, rate_hw, rate_ops, ++ gate_hw, gate_ops, CLK_IGNORE_UNUSED); + + if (IS_ERR(*hw)) + return PTR_ERR(*hw); +@@ -406,12 +408,11 @@ static int armada_3700_periph_clock_prob + if (armada_3700_add_composite_clk(&data[i], reg, + &driver_data->lock, dev, hw)) + dev_err(dev, "Can't register periph clock %s\n", +- data[i].name); +- ++ data[i].name); + } + + ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, +- driver_data->hw_data); ++ driver_data->hw_data); + if (ret) { + for (i = 0; i < num_periph; i++) + clk_hw_unregister(driver_data->hw_data->hws[i]); diff --git a/target/linux/mvebu/patches-4.14/503-cpufreq-Add-DVFS-support-for-Armada-37xx.patch b/target/linux/mvebu/patches-4.14/503-cpufreq-Add-DVFS-support-for-Armada-37xx.patch deleted file mode 100644 index 11562c582b..0000000000 --- a/target/linux/mvebu/patches-4.14/503-cpufreq-Add-DVFS-support-for-Armada-37xx.patch +++ /dev/null @@ -1,297 +0,0 @@ -From 92ce45fb875d7c3e021cc454482fe0687ff54f29 Mon Sep 17 00:00:00 2001 -From: Gregory CLEMENT -Date: Thu, 14 Dec 2017 16:00:05 +0100 -Subject: cpufreq: Add DVFS support for Armada 37xx - -This patch adds DVFS support for the Armada 37xx SoCs - -There are up to four CPU frequency loads for Armada 37xx controlled by -the hardware. - -This driver associates the CPU load level to a frequency, then the -hardware will switch while selecting a load level. - -The hardware also can associate a voltage for each level (AVS support) -but it is not yet supported - -Tested-by: Andre Heider -Acked-by: Viresh Kumar -Signed-off-by: Gregory CLEMENT -Signed-off-by: Rafael J. Wysocki ---- - drivers/cpufreq/Kconfig.arm | 7 + - drivers/cpufreq/Makefile | 1 + - drivers/cpufreq/armada-37xx-cpufreq.c | 241 ++++++++++++++++++++++++++++++++++ - 3 files changed, 249 insertions(+) - create mode 100644 drivers/cpufreq/armada-37xx-cpufreq.c - ---- a/drivers/cpufreq/Kconfig.arm -+++ b/drivers/cpufreq/Kconfig.arm -@@ -2,6 +2,13 @@ - # ARM CPU Frequency scaling drivers - # - -+config ARM_ARMADA_37XX_CPUFREQ -+ tristate "Armada 37xx CPUFreq support" -+ depends on ARCH_MVEBU -+ help -+ This adds the CPUFreq driver support for Marvell Armada 37xx SoCs. -+ The Armada 37xx PMU supports 4 frequency and VDD levels. -+ - # big LITTLE core layer and glue drivers - config ARM_BIG_LITTLE_CPUFREQ - tristate "Generic ARM big LITTLE CPUfreq driver" ---- a/drivers/cpufreq/Makefile -+++ b/drivers/cpufreq/Makefile -@@ -52,6 +52,7 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += - # LITTLE drivers, so that it is probed last. - obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o - -+obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o - obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o - obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o - obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o ---- /dev/null -+++ b/drivers/cpufreq/armada-37xx-cpufreq.c -@@ -0,0 +1,241 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * CPU frequency scaling support for Armada 37xx platform. -+ * -+ * Copyright (C) 2017 Marvell -+ * -+ * Gregory CLEMENT -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Power management in North Bridge register set */ -+#define ARMADA_37XX_NB_L0L1 0x18 -+#define ARMADA_37XX_NB_L2L3 0x1C -+#define ARMADA_37XX_NB_TBG_DIV_OFF 13 -+#define ARMADA_37XX_NB_TBG_DIV_MASK 0x7 -+#define ARMADA_37XX_NB_CLK_SEL_OFF 11 -+#define ARMADA_37XX_NB_CLK_SEL_MASK 0x1 -+#define ARMADA_37XX_NB_CLK_SEL_TBG 0x1 -+#define ARMADA_37XX_NB_TBG_SEL_OFF 9 -+#define ARMADA_37XX_NB_TBG_SEL_MASK 0x3 -+#define ARMADA_37XX_NB_VDD_SEL_OFF 6 -+#define ARMADA_37XX_NB_VDD_SEL_MASK 0x3 -+#define ARMADA_37XX_NB_CONFIG_SHIFT 16 -+#define ARMADA_37XX_NB_DYN_MOD 0x24 -+#define ARMADA_37XX_NB_CLK_SEL_EN BIT(26) -+#define ARMADA_37XX_NB_TBG_EN BIT(28) -+#define ARMADA_37XX_NB_DIV_EN BIT(29) -+#define ARMADA_37XX_NB_VDD_EN BIT(30) -+#define ARMADA_37XX_NB_DFS_EN BIT(31) -+#define ARMADA_37XX_NB_CPU_LOAD 0x30 -+#define ARMADA_37XX_NB_CPU_LOAD_MASK 0x3 -+#define ARMADA_37XX_DVFS_LOAD_0 0 -+#define ARMADA_37XX_DVFS_LOAD_1 1 -+#define ARMADA_37XX_DVFS_LOAD_2 2 -+#define ARMADA_37XX_DVFS_LOAD_3 3 -+ -+/* -+ * On Armada 37xx the Power management manages 4 level of CPU load, -+ * each level can be associated with a CPU clock source, a CPU -+ * divider, a VDD level, etc... -+ */ -+#define LOAD_LEVEL_NR 4 -+ -+struct armada_37xx_dvfs { -+ u32 cpu_freq_max; -+ u8 divider[LOAD_LEVEL_NR]; -+}; -+ -+static struct armada_37xx_dvfs armada_37xx_dvfs[] = { -+ {.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} }, -+ {.cpu_freq_max = 1000*1000*1000, .divider = {1, 2, 4, 5} }, -+ {.cpu_freq_max = 800*1000*1000, .divider = {1, 2, 3, 4} }, -+ {.cpu_freq_max = 600*1000*1000, .divider = {2, 4, 5, 6} }, -+}; -+ -+static struct armada_37xx_dvfs *armada_37xx_cpu_freq_info_get(u32 freq) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(armada_37xx_dvfs); i++) { -+ if (freq == armada_37xx_dvfs[i].cpu_freq_max) -+ return &armada_37xx_dvfs[i]; -+ } -+ -+ pr_err("Unsupported CPU frequency %d MHz\n", freq/1000000); -+ return NULL; -+} -+ -+/* -+ * Setup the four level managed by the hardware. Once the four level -+ * will be configured then the DVFS will be enabled. -+ */ -+static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base, -+ struct clk *clk, u8 *divider) -+{ -+ int load_lvl; -+ struct clk *parent; -+ -+ for (load_lvl = 0; load_lvl < LOAD_LEVEL_NR; load_lvl++) { -+ unsigned int reg, mask, val, offset = 0; -+ -+ if (load_lvl <= ARMADA_37XX_DVFS_LOAD_1) -+ reg = ARMADA_37XX_NB_L0L1; -+ else -+ reg = ARMADA_37XX_NB_L2L3; -+ -+ if (load_lvl == ARMADA_37XX_DVFS_LOAD_0 || -+ load_lvl == ARMADA_37XX_DVFS_LOAD_2) -+ offset += ARMADA_37XX_NB_CONFIG_SHIFT; -+ -+ /* Set cpu clock source, for all the level we use TBG */ -+ val = ARMADA_37XX_NB_CLK_SEL_TBG << ARMADA_37XX_NB_CLK_SEL_OFF; -+ mask = (ARMADA_37XX_NB_CLK_SEL_MASK -+ << ARMADA_37XX_NB_CLK_SEL_OFF); -+ -+ /* -+ * Set cpu divider based on the pre-computed array in -+ * order to have balanced step. -+ */ -+ val |= divider[load_lvl] << ARMADA_37XX_NB_TBG_DIV_OFF; -+ mask |= (ARMADA_37XX_NB_TBG_DIV_MASK -+ << ARMADA_37XX_NB_TBG_DIV_OFF); -+ -+ /* Set VDD divider which is actually the load level. */ -+ val |= load_lvl << ARMADA_37XX_NB_VDD_SEL_OFF; -+ mask |= (ARMADA_37XX_NB_VDD_SEL_MASK -+ << ARMADA_37XX_NB_VDD_SEL_OFF); -+ -+ val <<= offset; -+ mask <<= offset; -+ -+ regmap_update_bits(base, reg, mask, val); -+ } -+ -+ /* -+ * Set cpu clock source, for all the level we keep the same -+ * clock source that the one already configured. For this one -+ * we need to use the clock framework -+ */ -+ parent = clk_get_parent(clk); -+ clk_set_parent(clk, parent); -+} -+ -+static void __init armada37xx_cpufreq_disable_dvfs(struct regmap *base) -+{ -+ unsigned int reg = ARMADA_37XX_NB_DYN_MOD, -+ mask = ARMADA_37XX_NB_DFS_EN; -+ -+ regmap_update_bits(base, reg, mask, 0); -+} -+ -+static void __init armada37xx_cpufreq_enable_dvfs(struct regmap *base) -+{ -+ unsigned int val, reg = ARMADA_37XX_NB_CPU_LOAD, -+ mask = ARMADA_37XX_NB_CPU_LOAD_MASK; -+ -+ /* Start with the highest load (0) */ -+ val = ARMADA_37XX_DVFS_LOAD_0; -+ regmap_update_bits(base, reg, mask, val); -+ -+ /* Now enable DVFS for the CPUs */ -+ reg = ARMADA_37XX_NB_DYN_MOD; -+ mask = ARMADA_37XX_NB_CLK_SEL_EN | ARMADA_37XX_NB_TBG_EN | -+ ARMADA_37XX_NB_DIV_EN | ARMADA_37XX_NB_VDD_EN | -+ ARMADA_37XX_NB_DFS_EN; -+ -+ regmap_update_bits(base, reg, mask, mask); -+} -+ -+static int __init armada37xx_cpufreq_driver_init(void) -+{ -+ struct armada_37xx_dvfs *dvfs; -+ struct platform_device *pdev; -+ unsigned int cur_frequency; -+ struct regmap *nb_pm_base; -+ struct device *cpu_dev; -+ int load_lvl, ret; -+ struct clk *clk; -+ -+ nb_pm_base = -+ syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm"); -+ -+ if (IS_ERR(nb_pm_base)) -+ return -ENODEV; -+ -+ /* Before doing any configuration on the DVFS first, disable it */ -+ armada37xx_cpufreq_disable_dvfs(nb_pm_base); -+ -+ /* -+ * On CPU 0 register the operating points supported (which are -+ * the nominal CPU frequency and full integer divisions of -+ * it). -+ */ -+ cpu_dev = get_cpu_device(0); -+ if (!cpu_dev) { -+ dev_err(cpu_dev, "Cannot get CPU\n"); -+ return -ENODEV; -+ } -+ -+ clk = clk_get(cpu_dev, 0); -+ if (IS_ERR(clk)) { -+ dev_err(cpu_dev, "Cannot get clock for CPU0\n"); -+ return PTR_ERR(clk); -+ } -+ -+ /* Get nominal (current) CPU frequency */ -+ cur_frequency = clk_get_rate(clk); -+ if (!cur_frequency) { -+ dev_err(cpu_dev, "Failed to get clock rate for CPU\n"); -+ return -EINVAL; -+ } -+ -+ dvfs = armada_37xx_cpu_freq_info_get(cur_frequency); -+ if (!dvfs) -+ return -EINVAL; -+ -+ armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider); -+ -+ for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR; -+ load_lvl++) { -+ unsigned long freq = cur_frequency / dvfs->divider[load_lvl]; -+ -+ ret = dev_pm_opp_add(cpu_dev, freq, 0); -+ if (ret) { -+ /* clean-up the already added opp before leaving */ -+ while (load_lvl-- > ARMADA_37XX_DVFS_LOAD_0) { -+ freq = cur_frequency / dvfs->divider[load_lvl]; -+ dev_pm_opp_remove(cpu_dev, freq); -+ } -+ return ret; -+ } -+ } -+ -+ /* Now that everything is setup, enable the DVFS at hardware level */ -+ armada37xx_cpufreq_enable_dvfs(nb_pm_base); -+ -+ pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0); -+ -+ return PTR_ERR_OR_ZERO(pdev); -+} -+/* late_initcall, to guarantee the driver is loaded after A37xx clock driver */ -+late_initcall(armada37xx_cpufreq_driver_init); -+ -+MODULE_AUTHOR("Gregory CLEMENT "); -+MODULE_DESCRIPTION("Armada 37xx cpufreq driver"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/mvebu/patches-4.14/504-clk-mvebu-armada-37xx-periph-prepare-cpu-clk-to-be-u.patch b/target/linux/mvebu/patches-4.14/504-clk-mvebu-armada-37xx-periph-prepare-cpu-clk-to-be-u.patch new file mode 100644 index 0000000000..f9dec9f2ee --- /dev/null +++ b/target/linux/mvebu/patches-4.14/504-clk-mvebu-armada-37xx-periph-prepare-cpu-clk-to-be-u.patch @@ -0,0 +1,178 @@ +From 9818a7a4fd10f72537cdf2a5ec3402f2c245ea24 Mon Sep 17 00:00:00 2001 +From: Gregory CLEMENT +Date: Thu, 30 Nov 2017 14:40:28 +0100 +Subject: clk: mvebu: armada-37xx-periph: prepare cpu clk to be + used with DVFS + +When DVFS will be enabled then the cpu clk will use a different set of +register at run time. That means that we won't be able to use the common +callback and need to use our own ones. + +This patch prepares this change by switching on our own set of callbacks +without modifying the behavior of the clocks. + +Signed-off-by: Gregory CLEMENT +Signed-off-by: Stephen Boyd +--- + drivers/clk/mvebu/armada-37xx-periph.c | 82 ++++++++++++++++++++++++++++++---- + 1 file changed, 73 insertions(+), 9 deletions(-) + +--- a/drivers/clk/mvebu/armada-37xx-periph.c ++++ b/drivers/clk/mvebu/armada-37xx-periph.c +@@ -46,7 +46,17 @@ struct clk_double_div { + u8 shift2; + }; + ++struct clk_pm_cpu { ++ struct clk_hw hw; ++ void __iomem *reg_mux; ++ u8 shift_mux; ++ u32 mask_mux; ++ void __iomem *reg_div; ++ u8 shift_div; ++}; ++ + #define to_clk_double_div(_hw) container_of(_hw, struct clk_double_div, hw) ++#define to_clk_pm_cpu(_hw) container_of(_hw, struct clk_pm_cpu, hw) + + struct clk_periph_data { + const char *name; +@@ -55,6 +65,7 @@ struct clk_periph_data { + struct clk_hw *mux_hw; + struct clk_hw *rate_hw; + struct clk_hw *gate_hw; ++ struct clk_hw *muxrate_hw; + bool is_double_div; + }; + +@@ -81,6 +92,7 @@ static const struct clk_div_table clk_ta + }; + + static const struct clk_ops clk_double_div_ops; ++static const struct clk_ops clk_pm_cpu_ops; + + #define PERIPH_GATE(_name, _bit) \ + struct clk_gate gate_##_name = { \ +@@ -122,6 +134,18 @@ struct clk_divider rate_##_name = { \ + } \ + }; + ++#define PERIPH_PM_CPU(_name, _shift1, _reg, _shift2) \ ++struct clk_pm_cpu muxrate_##_name = { \ ++ .reg_mux = (void *)TBG_SEL, \ ++ .mask_mux = 3, \ ++ .shift_mux = _shift1, \ ++ .reg_div = (void *)_reg, \ ++ .shift_div = _shift2, \ ++ .hw.init = &(struct clk_init_data){ \ ++ .ops = &clk_pm_cpu_ops, \ ++ } \ ++}; ++ + #define PERIPH_CLK_FULL_DD(_name, _bit, _shift, _reg1, _reg2, _shift1, _shift2)\ + static PERIPH_GATE(_name, _bit); \ + static PERIPH_MUX(_name, _shift); \ +@@ -136,10 +160,6 @@ static PERIPH_DIV(_name, _reg, _shift1, + static PERIPH_GATE(_name, _bit); \ + static PERIPH_DIV(_name, _reg, _shift, _table); + +-#define PERIPH_CLK_MUX_DIV(_name, _shift, _reg, _shift_div, _table) \ +-static PERIPH_MUX(_name, _shift); \ +-static PERIPH_DIV(_name, _reg, _shift_div, _table); +- + #define PERIPH_CLK_MUX_DD(_name, _shift, _reg1, _reg2, _shift1, _shift2)\ + static PERIPH_MUX(_name, _shift); \ + static PERIPH_DOUBLEDIV(_name, _reg1, _reg2, _shift1, _shift2); +@@ -180,13 +200,12 @@ static PERIPH_DOUBLEDIV(_name, _reg1, _r + .rate_hw = &rate_##_name.hw, \ + } + +-#define REF_CLK_MUX_DIV(_name) \ ++#define REF_CLK_PM_CPU(_name) \ + { .name = #_name, \ + .parent_names = (const char *[]){ "TBG-A-P", \ + "TBG-B-P", "TBG-A-S", "TBG-B-S"}, \ + .num_parents = 4, \ +- .mux_hw = &mux_##_name.hw, \ +- .rate_hw = &rate_##_name.hw, \ ++ .muxrate_hw = &muxrate_##_name.hw, \ + } + + #define REF_CLK_MUX_DD(_name) \ +@@ -216,7 +235,7 @@ PERIPH_CLK_FULL_DD(ddr_fclk, 21, 16, DIV + PERIPH_CLK_FULL(trace, 22, 18, DIV_SEL0, 20, clk_table6); + PERIPH_CLK_FULL(counter, 23, 20, DIV_SEL0, 23, clk_table6); + PERIPH_CLK_FULL_DD(eip97, 24, 24, DIV_SEL2, DIV_SEL2, 22, 19); +-PERIPH_CLK_MUX_DIV(cpu, 22, DIV_SEL0, 28, clk_table6); ++static PERIPH_PM_CPU(cpu, 22, DIV_SEL0, 28); + + static struct clk_periph_data data_nb[] = { + REF_CLK_FULL_DD(mmc), +@@ -235,7 +254,7 @@ static struct clk_periph_data data_nb[] + REF_CLK_FULL(trace), + REF_CLK_FULL(counter), + REF_CLK_FULL_DD(eip97), +- REF_CLK_MUX_DIV(cpu), ++ REF_CLK_PM_CPU(cpu), + { }, + }; + +@@ -297,6 +316,37 @@ static const struct clk_ops clk_double_d + .recalc_rate = clk_double_div_recalc_rate, + }; + ++static u8 clk_pm_cpu_get_parent(struct clk_hw *hw) ++{ ++ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); ++ int num_parents = clk_hw_get_num_parents(hw); ++ u32 val; ++ ++ val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux; ++ val &= pm_cpu->mask_mux; ++ ++ if (val >= num_parents) ++ return -EINVAL; ++ ++ return val; ++} ++ ++static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); ++ unsigned int div; ++ ++ div = get_div(pm_cpu->reg_div, pm_cpu->shift_div); ++ ++ return DIV_ROUND_UP_ULL((u64)parent_rate, div); ++} ++ ++static const struct clk_ops clk_pm_cpu_ops = { ++ .get_parent = clk_pm_cpu_get_parent, ++ .recalc_rate = clk_pm_cpu_recalc_rate, ++}; ++ + static const struct of_device_id armada_3700_periph_clock_of_match[] = { + { .compatible = "marvell,armada-3700-periph-clock-nb", + .data = data_nb, }, +@@ -356,6 +406,20 @@ static int armada_3700_add_composite_clk + } + } + ++ if (data->muxrate_hw) { ++ struct clk_pm_cpu *pmcpu_clk; ++ struct clk_hw *muxrate_hw = data->muxrate_hw; ++ ++ pmcpu_clk = to_clk_pm_cpu(muxrate_hw); ++ pmcpu_clk->reg_mux = reg + (u64)pmcpu_clk->reg_mux; ++ pmcpu_clk->reg_div = reg + (u64)pmcpu_clk->reg_div; ++ ++ mux_hw = muxrate_hw; ++ rate_hw = muxrate_hw; ++ mux_ops = muxrate_hw->init->ops; ++ rate_ops = muxrate_hw->init->ops; ++ } ++ + *hw = clk_hw_register_composite(dev, data->name, data->parent_names, + data->num_parents, mux_hw, + mux_ops, rate_hw, rate_ops, diff --git a/target/linux/mvebu/patches-4.14/504-spi-a3700-Change-SPI-mode-before-asserting-chip-sele.patch b/target/linux/mvebu/patches-4.14/504-spi-a3700-Change-SPI-mode-before-asserting-chip-sele.patch deleted file mode 100644 index 3ac7091188..0000000000 --- a/target/linux/mvebu/patches-4.14/504-spi-a3700-Change-SPI-mode-before-asserting-chip-sele.patch +++ /dev/null @@ -1,70 +0,0 @@ -From dd7aa8d4b53b3484ba31ba56f3ff1be7deb38530 Mon Sep 17 00:00:00 2001 -From: Maxime Chevallier -Date: Tue, 10 Oct 2017 10:43:18 +0200 -Subject: spi: a3700: Change SPI mode before asserting chip-select - -The spi device mode should be configured in the controller before the -chip-select is asserted, so that a clock polarity configuration change -is not interpreted as a clock tick by the device. - -This patch moves the mode setting to the 'prepare_message' function -instead of the 'transfer_one' function. - -By doing so, this patch also removes redundant code in -a3700_spi_clock_set. - -This was tested on EspressoBin board, with spidev. - -Signed-off-by: Maxime Chevallier -Signed-off-by: Mark Brown ---- - drivers/spi/spi-armada-3700.c | 17 ++++------------- - 1 file changed, 4 insertions(+), 13 deletions(-) - ---- a/drivers/spi/spi-armada-3700.c -+++ b/drivers/spi/spi-armada-3700.c -@@ -214,7 +214,7 @@ static void a3700_spi_mode_set(struct a3 - } - - static void a3700_spi_clock_set(struct a3700_spi *a3700_spi, -- unsigned int speed_hz, u16 mode) -+ unsigned int speed_hz) - { - u32 val; - u32 prescale; -@@ -239,17 +239,6 @@ static void a3700_spi_clock_set(struct a - val |= A3700_SPI_CLK_CAPT_EDGE; - spireg_write(a3700_spi, A3700_SPI_IF_TIME_REG, val); - } -- -- val = spireg_read(a3700_spi, A3700_SPI_IF_CFG_REG); -- val &= ~(A3700_SPI_CLK_POL | A3700_SPI_CLK_PHA); -- -- if (mode & SPI_CPOL) -- val |= A3700_SPI_CLK_POL; -- -- if (mode & SPI_CPHA) -- val |= A3700_SPI_CLK_PHA; -- -- spireg_write(a3700_spi, A3700_SPI_IF_CFG_REG, val); - } - - static void a3700_spi_bytelen_set(struct a3700_spi *a3700_spi, unsigned int len) -@@ -431,7 +420,7 @@ static void a3700_spi_transfer_setup(str - - a3700_spi = spi_master_get_devdata(spi->master); - -- a3700_spi_clock_set(a3700_spi, xfer->speed_hz, spi->mode); -+ a3700_spi_clock_set(a3700_spi, xfer->speed_hz); - - byte_len = xfer->bits_per_word >> 3; - -@@ -592,6 +581,8 @@ static int a3700_spi_prepare_message(str - - a3700_spi_bytelen_set(a3700_spi, 4); - -+ a3700_spi_mode_set(a3700_spi, spi->mode); -+ - return 0; - } - diff --git a/target/linux/mvebu/patches-4.14/505-arm64-dts-marvell-Fix-A37xx-UART0-register-size.patch b/target/linux/mvebu/patches-4.14/505-arm64-dts-marvell-Fix-A37xx-UART0-register-size.patch deleted file mode 100644 index 9e2b1c14eb..0000000000 --- a/target/linux/mvebu/patches-4.14/505-arm64-dts-marvell-Fix-A37xx-UART0-register-size.patch +++ /dev/null @@ -1,39 +0,0 @@ -From c737abc193d16e62e23e2fb585b8b7398ab380d8 Mon Sep 17 00:00:00 2001 -From: allen yan -Date: Thu, 7 Sep 2017 15:04:53 +0200 -Subject: arm64: dts: marvell: Fix A37xx UART0 register size - -Armada-37xx UART0 registers are 0x200 bytes wide. Right next to them are -the UART1 registers that should not be declared in this node. - -Update the example in DT bindings document accordingly. - -Signed-off-by: allen yan -Signed-off-by: Miquel Raynal -Signed-off-by: Gregory CLEMENT ---- - Documentation/devicetree/bindings/serial/mvebu-uart.txt | 2 +- - arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - ---- a/Documentation/devicetree/bindings/serial/mvebu-uart.txt -+++ b/Documentation/devicetree/bindings/serial/mvebu-uart.txt -@@ -8,6 +8,6 @@ Required properties: - Example: - serial@12000 { - compatible = "marvell,armada-3700-uart"; -- reg = <0x12000 0x400>; -+ reg = <0x12000 0x200>; - interrupts = <43>; - }; ---- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi -+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi -@@ -134,7 +134,7 @@ - - uart0: serial@12000 { - compatible = "marvell,armada-3700-uart"; -- reg = <0x12000 0x400>; -+ reg = <0x12000 0x200>; - interrupts = ; - status = "disabled"; - }; diff --git a/target/linux/mvebu/patches-4.14/505-clk-mvebu-armada-37xx-periph-add-DVFS-support-for-cp.patch b/target/linux/mvebu/patches-4.14/505-clk-mvebu-armada-37xx-periph-add-DVFS-support-for-cp.patch new file mode 100644 index 0000000000..2065e788af --- /dev/null +++ b/target/linux/mvebu/patches-4.14/505-clk-mvebu-armada-37xx-periph-add-DVFS-support-for-cp.patch @@ -0,0 +1,315 @@ +From 2089dc33ea0e3917465929d4020fbff3d6dbf7f4 Mon Sep 17 00:00:00 2001 +From: Gregory CLEMENT +Date: Thu, 30 Nov 2017 14:40:29 +0100 +Subject: clk: mvebu: armada-37xx-periph: add DVFS support for cpu clocks + +When DVFS is enabled the CPU clock setting is done using an other set of +registers. + +These Power Management registers are exposed through a syscon as they +will also be used by other drivers such as the cpufreq. + +This patch add the possibility to modify the CPU frequency using the +associate load level matching the target frequency. Then all the +frequency switch is handle by the hardware. + +Signed-off-by: Gregory CLEMENT +[sboyd@codeaurora.org: Grow a local variable for regmap pointer +to keep lines shorter] +Signed-off-by: Stephen Boyd +--- + drivers/clk/mvebu/armada-37xx-periph.c | 221 ++++++++++++++++++++++++++++++++- + 1 file changed, 217 insertions(+), 4 deletions(-) + +--- a/drivers/clk/mvebu/armada-37xx-periph.c ++++ b/drivers/clk/mvebu/armada-37xx-periph.c +@@ -21,9 +21,11 @@ + */ + + #include ++#include + #include + #include + #include ++#include + #include + + #define TBG_SEL 0x0 +@@ -33,6 +35,26 @@ + #define CLK_SEL 0x10 + #define CLK_DIS 0x14 + ++#define LOAD_LEVEL_NR 4 ++ ++#define ARMADA_37XX_NB_L0L1 0x18 ++#define ARMADA_37XX_NB_L2L3 0x1C ++#define ARMADA_37XX_NB_TBG_DIV_OFF 13 ++#define ARMADA_37XX_NB_TBG_DIV_MASK 0x7 ++#define ARMADA_37XX_NB_CLK_SEL_OFF 11 ++#define ARMADA_37XX_NB_CLK_SEL_MASK 0x1 ++#define ARMADA_37XX_NB_TBG_SEL_OFF 9 ++#define ARMADA_37XX_NB_TBG_SEL_MASK 0x3 ++#define ARMADA_37XX_NB_CONFIG_SHIFT 16 ++#define ARMADA_37XX_NB_DYN_MOD 0x24 ++#define ARMADA_37XX_NB_DFS_EN 31 ++#define ARMADA_37XX_NB_CPU_LOAD 0x30 ++#define ARMADA_37XX_NB_CPU_LOAD_MASK 0x3 ++#define ARMADA_37XX_DVFS_LOAD_0 0 ++#define ARMADA_37XX_DVFS_LOAD_1 1 ++#define ARMADA_37XX_DVFS_LOAD_2 2 ++#define ARMADA_37XX_DVFS_LOAD_3 3 ++ + struct clk_periph_driver_data { + struct clk_hw_onecell_data *hw_data; + spinlock_t lock; +@@ -53,6 +75,7 @@ struct clk_pm_cpu { + u32 mask_mux; + void __iomem *reg_div; + u8 shift_div; ++ struct regmap *nb_pm_base; + }; + + #define to_clk_double_div(_hw) container_of(_hw, struct clk_double_div, hw) +@@ -316,14 +339,94 @@ static const struct clk_ops clk_double_d + .recalc_rate = clk_double_div_recalc_rate, + }; + ++static void armada_3700_pm_dvfs_update_regs(unsigned int load_level, ++ unsigned int *reg, ++ unsigned int *offset) ++{ ++ if (load_level <= ARMADA_37XX_DVFS_LOAD_1) ++ *reg = ARMADA_37XX_NB_L0L1; ++ else ++ *reg = ARMADA_37XX_NB_L2L3; ++ ++ if (load_level == ARMADA_37XX_DVFS_LOAD_0 || ++ load_level == ARMADA_37XX_DVFS_LOAD_2) ++ *offset += ARMADA_37XX_NB_CONFIG_SHIFT; ++} ++ ++static bool armada_3700_pm_dvfs_is_enabled(struct regmap *base) ++{ ++ unsigned int val, reg = ARMADA_37XX_NB_DYN_MOD; ++ ++ if (IS_ERR(base)) ++ return false; ++ ++ regmap_read(base, reg, &val); ++ ++ return !!(val & BIT(ARMADA_37XX_NB_DFS_EN)); ++} ++ ++static unsigned int armada_3700_pm_dvfs_get_cpu_div(struct regmap *base) ++{ ++ unsigned int reg = ARMADA_37XX_NB_CPU_LOAD; ++ unsigned int offset = ARMADA_37XX_NB_TBG_DIV_OFF; ++ unsigned int load_level, div; ++ ++ /* ++ * This function is always called after the function ++ * armada_3700_pm_dvfs_is_enabled, so no need to check again ++ * if the base is valid. ++ */ ++ regmap_read(base, reg, &load_level); ++ ++ /* ++ * The register and the offset inside this register accessed to ++ * read the current divider depend on the load level ++ */ ++ load_level &= ARMADA_37XX_NB_CPU_LOAD_MASK; ++ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset); ++ ++ regmap_read(base, reg, &div); ++ ++ return (div >> offset) & ARMADA_37XX_NB_TBG_DIV_MASK; ++} ++ ++static unsigned int armada_3700_pm_dvfs_get_cpu_parent(struct regmap *base) ++{ ++ unsigned int reg = ARMADA_37XX_NB_CPU_LOAD; ++ unsigned int offset = ARMADA_37XX_NB_TBG_SEL_OFF; ++ unsigned int load_level, sel; ++ ++ /* ++ * This function is always called after the function ++ * armada_3700_pm_dvfs_is_enabled, so no need to check again ++ * if the base is valid ++ */ ++ regmap_read(base, reg, &load_level); ++ ++ /* ++ * The register and the offset inside this register accessed to ++ * read the current divider depend on the load level ++ */ ++ load_level &= ARMADA_37XX_NB_CPU_LOAD_MASK; ++ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset); ++ ++ regmap_read(base, reg, &sel); ++ ++ return (sel >> offset) & ARMADA_37XX_NB_TBG_SEL_MASK; ++} ++ + static u8 clk_pm_cpu_get_parent(struct clk_hw *hw) + { + struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); + int num_parents = clk_hw_get_num_parents(hw); + u32 val; + +- val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux; +- val &= pm_cpu->mask_mux; ++ if (armada_3700_pm_dvfs_is_enabled(pm_cpu->nb_pm_base)) { ++ val = armada_3700_pm_dvfs_get_cpu_parent(pm_cpu->nb_pm_base); ++ } else { ++ val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux; ++ val &= pm_cpu->mask_mux; ++ } + + if (val >= num_parents) + return -EINVAL; +@@ -331,19 +434,124 @@ static u8 clk_pm_cpu_get_parent(struct c + return val; + } + ++static int clk_pm_cpu_set_parent(struct clk_hw *hw, u8 index) ++{ ++ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); ++ struct regmap *base = pm_cpu->nb_pm_base; ++ int load_level; ++ ++ /* ++ * We set the clock parent only if the DVFS is available but ++ * not enabled. ++ */ ++ if (IS_ERR(base) || armada_3700_pm_dvfs_is_enabled(base)) ++ return -EINVAL; ++ ++ /* Set the parent clock for all the load level */ ++ for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) { ++ unsigned int reg, mask, val, ++ offset = ARMADA_37XX_NB_TBG_SEL_OFF; ++ ++ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset); ++ ++ val = index << offset; ++ mask = ARMADA_37XX_NB_TBG_SEL_MASK << offset; ++ regmap_update_bits(base, reg, mask, val); ++ } ++ return 0; ++} ++ + static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) + { + struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); + unsigned int div; + +- div = get_div(pm_cpu->reg_div, pm_cpu->shift_div); +- ++ if (armada_3700_pm_dvfs_is_enabled(pm_cpu->nb_pm_base)) ++ div = armada_3700_pm_dvfs_get_cpu_div(pm_cpu->nb_pm_base); ++ else ++ div = get_div(pm_cpu->reg_div, pm_cpu->shift_div); + return DIV_ROUND_UP_ULL((u64)parent_rate, div); + } + ++static long clk_pm_cpu_round_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *parent_rate) ++{ ++ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); ++ struct regmap *base = pm_cpu->nb_pm_base; ++ unsigned int div = *parent_rate / rate; ++ unsigned int load_level; ++ /* only available when DVFS is enabled */ ++ if (!armada_3700_pm_dvfs_is_enabled(base)) ++ return -EINVAL; ++ ++ for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) { ++ unsigned int reg, val, offset = ARMADA_37XX_NB_TBG_DIV_OFF; ++ ++ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset); ++ ++ regmap_read(base, reg, &val); ++ ++ val >>= offset; ++ val &= ARMADA_37XX_NB_TBG_DIV_MASK; ++ if (val == div) ++ /* ++ * We found a load level matching the target ++ * divider, switch to this load level and ++ * return. ++ */ ++ return *parent_rate / div; ++ } ++ ++ /* We didn't find any valid divider */ ++ return -EINVAL; ++} ++ ++static int clk_pm_cpu_set_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); ++ struct regmap *base = pm_cpu->nb_pm_base; ++ unsigned int div = parent_rate / rate; ++ unsigned int load_level; ++ ++ /* only available when DVFS is enabled */ ++ if (!armada_3700_pm_dvfs_is_enabled(base)) ++ return -EINVAL; ++ ++ for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) { ++ unsigned int reg, mask, val, ++ offset = ARMADA_37XX_NB_TBG_DIV_OFF; ++ ++ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset); ++ ++ regmap_read(base, reg, &val); ++ val >>= offset; ++ val &= ARMADA_37XX_NB_TBG_DIV_MASK; ++ ++ if (val == div) { ++ /* ++ * We found a load level matching the target ++ * divider, switch to this load level and ++ * return. ++ */ ++ reg = ARMADA_37XX_NB_CPU_LOAD; ++ mask = ARMADA_37XX_NB_CPU_LOAD_MASK; ++ regmap_update_bits(base, reg, mask, load_level); ++ ++ return rate; ++ } ++ } ++ ++ /* We didn't find any valid divider */ ++ return -EINVAL; ++} ++ + static const struct clk_ops clk_pm_cpu_ops = { + .get_parent = clk_pm_cpu_get_parent, ++ .set_parent = clk_pm_cpu_set_parent, ++ .round_rate = clk_pm_cpu_round_rate, ++ .set_rate = clk_pm_cpu_set_rate, + .recalc_rate = clk_pm_cpu_recalc_rate, + }; + +@@ -409,6 +617,7 @@ static int armada_3700_add_composite_clk + if (data->muxrate_hw) { + struct clk_pm_cpu *pmcpu_clk; + struct clk_hw *muxrate_hw = data->muxrate_hw; ++ struct regmap *map; + + pmcpu_clk = to_clk_pm_cpu(muxrate_hw); + pmcpu_clk->reg_mux = reg + (u64)pmcpu_clk->reg_mux; +@@ -418,6 +627,10 @@ static int armada_3700_add_composite_clk + rate_hw = muxrate_hw; + mux_ops = muxrate_hw->init->ops; + rate_ops = muxrate_hw->init->ops; ++ ++ map = syscon_regmap_lookup_by_compatible( ++ "marvell,armada-3700-nb-pm"); ++ pmcpu_clk->nb_pm_base = map; + } + + *hw = clk_hw_register_composite(dev, data->name, data->parent_names, diff --git a/target/linux/mvebu/patches-4.14/506-arm64-dts-marvell-armada-37xx-add-UART-clock.patch b/target/linux/mvebu/patches-4.14/506-arm64-dts-marvell-armada-37xx-add-UART-clock.patch deleted file mode 100644 index 47e0751c5f..0000000000 --- a/target/linux/mvebu/patches-4.14/506-arm64-dts-marvell-armada-37xx-add-UART-clock.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 2ff0d0b5bb397c3dc5c9b97bd0f20948f0b77740 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Fri, 13 Oct 2017 11:01:57 +0200 -Subject: arm64: dts: marvell: armada-37xx: add UART clock - -Add the missing clock property to armada-3700 UART node. - -This clock will be used to derive the prescaler value to comply with -the requested baudrate. - -Signed-off-by: Miquel Raynal -Acked-by: Gregory CLEMENT -Signed-off-by: Gregory CLEMENT ---- - arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi -+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi -@@ -135,6 +135,7 @@ - uart0: serial@12000 { - compatible = "marvell,armada-3700-uart"; - reg = <0x12000 0x200>; -+ clocks = <&xtalclk>; - interrupts = ; - status = "disabled"; - }; diff --git a/target/linux/mvebu/patches-4.14/506-cpufreq-Add-DVFS-support-for-Armada-37xx.patch b/target/linux/mvebu/patches-4.14/506-cpufreq-Add-DVFS-support-for-Armada-37xx.patch new file mode 100644 index 0000000000..11562c582b --- /dev/null +++ b/target/linux/mvebu/patches-4.14/506-cpufreq-Add-DVFS-support-for-Armada-37xx.patch @@ -0,0 +1,297 @@ +From 92ce45fb875d7c3e021cc454482fe0687ff54f29 Mon Sep 17 00:00:00 2001 +From: Gregory CLEMENT +Date: Thu, 14 Dec 2017 16:00:05 +0100 +Subject: cpufreq: Add DVFS support for Armada 37xx + +This patch adds DVFS support for the Armada 37xx SoCs + +There are up to four CPU frequency loads for Armada 37xx controlled by +the hardware. + +This driver associates the CPU load level to a frequency, then the +hardware will switch while selecting a load level. + +The hardware also can associate a voltage for each level (AVS support) +but it is not yet supported + +Tested-by: Andre Heider +Acked-by: Viresh Kumar +Signed-off-by: Gregory CLEMENT +Signed-off-by: Rafael J. Wysocki +--- + drivers/cpufreq/Kconfig.arm | 7 + + drivers/cpufreq/Makefile | 1 + + drivers/cpufreq/armada-37xx-cpufreq.c | 241 ++++++++++++++++++++++++++++++++++ + 3 files changed, 249 insertions(+) + create mode 100644 drivers/cpufreq/armada-37xx-cpufreq.c + +--- a/drivers/cpufreq/Kconfig.arm ++++ b/drivers/cpufreq/Kconfig.arm +@@ -2,6 +2,13 @@ + # ARM CPU Frequency scaling drivers + # + ++config ARM_ARMADA_37XX_CPUFREQ ++ tristate "Armada 37xx CPUFreq support" ++ depends on ARCH_MVEBU ++ help ++ This adds the CPUFreq driver support for Marvell Armada 37xx SoCs. ++ The Armada 37xx PMU supports 4 frequency and VDD levels. ++ + # big LITTLE core layer and glue drivers + config ARM_BIG_LITTLE_CPUFREQ + tristate "Generic ARM big LITTLE CPUfreq driver" +--- a/drivers/cpufreq/Makefile ++++ b/drivers/cpufreq/Makefile +@@ -52,6 +52,7 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += + # LITTLE drivers, so that it is probed last. + obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o + ++obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o + obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o + obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o + obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o +--- /dev/null ++++ b/drivers/cpufreq/armada-37xx-cpufreq.c +@@ -0,0 +1,241 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * CPU frequency scaling support for Armada 37xx platform. ++ * ++ * Copyright (C) 2017 Marvell ++ * ++ * Gregory CLEMENT ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Power management in North Bridge register set */ ++#define ARMADA_37XX_NB_L0L1 0x18 ++#define ARMADA_37XX_NB_L2L3 0x1C ++#define ARMADA_37XX_NB_TBG_DIV_OFF 13 ++#define ARMADA_37XX_NB_TBG_DIV_MASK 0x7 ++#define ARMADA_37XX_NB_CLK_SEL_OFF 11 ++#define ARMADA_37XX_NB_CLK_SEL_MASK 0x1 ++#define ARMADA_37XX_NB_CLK_SEL_TBG 0x1 ++#define ARMADA_37XX_NB_TBG_SEL_OFF 9 ++#define ARMADA_37XX_NB_TBG_SEL_MASK 0x3 ++#define ARMADA_37XX_NB_VDD_SEL_OFF 6 ++#define ARMADA_37XX_NB_VDD_SEL_MASK 0x3 ++#define ARMADA_37XX_NB_CONFIG_SHIFT 16 ++#define ARMADA_37XX_NB_DYN_MOD 0x24 ++#define ARMADA_37XX_NB_CLK_SEL_EN BIT(26) ++#define ARMADA_37XX_NB_TBG_EN BIT(28) ++#define ARMADA_37XX_NB_DIV_EN BIT(29) ++#define ARMADA_37XX_NB_VDD_EN BIT(30) ++#define ARMADA_37XX_NB_DFS_EN BIT(31) ++#define ARMADA_37XX_NB_CPU_LOAD 0x30 ++#define ARMADA_37XX_NB_CPU_LOAD_MASK 0x3 ++#define ARMADA_37XX_DVFS_LOAD_0 0 ++#define ARMADA_37XX_DVFS_LOAD_1 1 ++#define ARMADA_37XX_DVFS_LOAD_2 2 ++#define ARMADA_37XX_DVFS_LOAD_3 3 ++ ++/* ++ * On Armada 37xx the Power management manages 4 level of CPU load, ++ * each level can be associated with a CPU clock source, a CPU ++ * divider, a VDD level, etc... ++ */ ++#define LOAD_LEVEL_NR 4 ++ ++struct armada_37xx_dvfs { ++ u32 cpu_freq_max; ++ u8 divider[LOAD_LEVEL_NR]; ++}; ++ ++static struct armada_37xx_dvfs armada_37xx_dvfs[] = { ++ {.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} }, ++ {.cpu_freq_max = 1000*1000*1000, .divider = {1, 2, 4, 5} }, ++ {.cpu_freq_max = 800*1000*1000, .divider = {1, 2, 3, 4} }, ++ {.cpu_freq_max = 600*1000*1000, .divider = {2, 4, 5, 6} }, ++}; ++ ++static struct armada_37xx_dvfs *armada_37xx_cpu_freq_info_get(u32 freq) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(armada_37xx_dvfs); i++) { ++ if (freq == armada_37xx_dvfs[i].cpu_freq_max) ++ return &armada_37xx_dvfs[i]; ++ } ++ ++ pr_err("Unsupported CPU frequency %d MHz\n", freq/1000000); ++ return NULL; ++} ++ ++/* ++ * Setup the four level managed by the hardware. Once the four level ++ * will be configured then the DVFS will be enabled. ++ */ ++static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base, ++ struct clk *clk, u8 *divider) ++{ ++ int load_lvl; ++ struct clk *parent; ++ ++ for (load_lvl = 0; load_lvl < LOAD_LEVEL_NR; load_lvl++) { ++ unsigned int reg, mask, val, offset = 0; ++ ++ if (load_lvl <= ARMADA_37XX_DVFS_LOAD_1) ++ reg = ARMADA_37XX_NB_L0L1; ++ else ++ reg = ARMADA_37XX_NB_L2L3; ++ ++ if (load_lvl == ARMADA_37XX_DVFS_LOAD_0 || ++ load_lvl == ARMADA_37XX_DVFS_LOAD_2) ++ offset += ARMADA_37XX_NB_CONFIG_SHIFT; ++ ++ /* Set cpu clock source, for all the level we use TBG */ ++ val = ARMADA_37XX_NB_CLK_SEL_TBG << ARMADA_37XX_NB_CLK_SEL_OFF; ++ mask = (ARMADA_37XX_NB_CLK_SEL_MASK ++ << ARMADA_37XX_NB_CLK_SEL_OFF); ++ ++ /* ++ * Set cpu divider based on the pre-computed array in ++ * order to have balanced step. ++ */ ++ val |= divider[load_lvl] << ARMADA_37XX_NB_TBG_DIV_OFF; ++ mask |= (ARMADA_37XX_NB_TBG_DIV_MASK ++ << ARMADA_37XX_NB_TBG_DIV_OFF); ++ ++ /* Set VDD divider which is actually the load level. */ ++ val |= load_lvl << ARMADA_37XX_NB_VDD_SEL_OFF; ++ mask |= (ARMADA_37XX_NB_VDD_SEL_MASK ++ << ARMADA_37XX_NB_VDD_SEL_OFF); ++ ++ val <<= offset; ++ mask <<= offset; ++ ++ regmap_update_bits(base, reg, mask, val); ++ } ++ ++ /* ++ * Set cpu clock source, for all the level we keep the same ++ * clock source that the one already configured. For this one ++ * we need to use the clock framework ++ */ ++ parent = clk_get_parent(clk); ++ clk_set_parent(clk, parent); ++} ++ ++static void __init armada37xx_cpufreq_disable_dvfs(struct regmap *base) ++{ ++ unsigned int reg = ARMADA_37XX_NB_DYN_MOD, ++ mask = ARMADA_37XX_NB_DFS_EN; ++ ++ regmap_update_bits(base, reg, mask, 0); ++} ++ ++static void __init armada37xx_cpufreq_enable_dvfs(struct regmap *base) ++{ ++ unsigned int val, reg = ARMADA_37XX_NB_CPU_LOAD, ++ mask = ARMADA_37XX_NB_CPU_LOAD_MASK; ++ ++ /* Start with the highest load (0) */ ++ val = ARMADA_37XX_DVFS_LOAD_0; ++ regmap_update_bits(base, reg, mask, val); ++ ++ /* Now enable DVFS for the CPUs */ ++ reg = ARMADA_37XX_NB_DYN_MOD; ++ mask = ARMADA_37XX_NB_CLK_SEL_EN | ARMADA_37XX_NB_TBG_EN | ++ ARMADA_37XX_NB_DIV_EN | ARMADA_37XX_NB_VDD_EN | ++ ARMADA_37XX_NB_DFS_EN; ++ ++ regmap_update_bits(base, reg, mask, mask); ++} ++ ++static int __init armada37xx_cpufreq_driver_init(void) ++{ ++ struct armada_37xx_dvfs *dvfs; ++ struct platform_device *pdev; ++ unsigned int cur_frequency; ++ struct regmap *nb_pm_base; ++ struct device *cpu_dev; ++ int load_lvl, ret; ++ struct clk *clk; ++ ++ nb_pm_base = ++ syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm"); ++ ++ if (IS_ERR(nb_pm_base)) ++ return -ENODEV; ++ ++ /* Before doing any configuration on the DVFS first, disable it */ ++ armada37xx_cpufreq_disable_dvfs(nb_pm_base); ++ ++ /* ++ * On CPU 0 register the operating points supported (which are ++ * the nominal CPU frequency and full integer divisions of ++ * it). ++ */ ++ cpu_dev = get_cpu_device(0); ++ if (!cpu_dev) { ++ dev_err(cpu_dev, "Cannot get CPU\n"); ++ return -ENODEV; ++ } ++ ++ clk = clk_get(cpu_dev, 0); ++ if (IS_ERR(clk)) { ++ dev_err(cpu_dev, "Cannot get clock for CPU0\n"); ++ return PTR_ERR(clk); ++ } ++ ++ /* Get nominal (current) CPU frequency */ ++ cur_frequency = clk_get_rate(clk); ++ if (!cur_frequency) { ++ dev_err(cpu_dev, "Failed to get clock rate for CPU\n"); ++ return -EINVAL; ++ } ++ ++ dvfs = armada_37xx_cpu_freq_info_get(cur_frequency); ++ if (!dvfs) ++ return -EINVAL; ++ ++ armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider); ++ ++ for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR; ++ load_lvl++) { ++ unsigned long freq = cur_frequency / dvfs->divider[load_lvl]; ++ ++ ret = dev_pm_opp_add(cpu_dev, freq, 0); ++ if (ret) { ++ /* clean-up the already added opp before leaving */ ++ while (load_lvl-- > ARMADA_37XX_DVFS_LOAD_0) { ++ freq = cur_frequency / dvfs->divider[load_lvl]; ++ dev_pm_opp_remove(cpu_dev, freq); ++ } ++ return ret; ++ } ++ } ++ ++ /* Now that everything is setup, enable the DVFS at hardware level */ ++ armada37xx_cpufreq_enable_dvfs(nb_pm_base); ++ ++ pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0); ++ ++ return PTR_ERR_OR_ZERO(pdev); ++} ++/* late_initcall, to guarantee the driver is loaded after A37xx clock driver */ ++late_initcall(armada37xx_cpufreq_driver_init); ++ ++MODULE_AUTHOR("Gregory CLEMENT "); ++MODULE_DESCRIPTION("Armada 37xx cpufreq driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/mvebu/patches-4.14/508-arm64-dts-armada-3720-espressobin-wire-up-spi-flash.patch b/target/linux/mvebu/patches-4.14/508-arm64-dts-armada-3720-espressobin-wire-up-spi-flash.patch new file mode 100644 index 0000000000..fb80db7e89 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/508-arm64-dts-armada-3720-espressobin-wire-up-spi-flash.patch @@ -0,0 +1,45 @@ +From bffed3d4abcd32ba6d492a9bd7ebe81dc92eaa9a Mon Sep 17 00:00:00 2001 +From: Ellie Reeves +Date: Sun, 25 Mar 2018 21:57:36 +0200 +Subject: [PATCH] arm64: dts: armada-3720-espressobin: wire up spi flash +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is the storage the machine boots from by default. The partitioning +is taken from the U-Boot that is shipped with the board. There is some +more space on the flash that isn't used. + +Tested-by: Gregory CLEMENT +Signed-off-by: Ellie Reeves +Signed-off-by: Uwe Kleine-König +Signed-off-by: Gregory CLEMENT + +[drop partitions, not every U-Boot has same layout] +Signed-off-by: Tomasz Maciej Nowak +--- + .../dts/marvell/armada-3720-espressobin.dts | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts ++++ b/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts +@@ -96,6 +96,19 @@ + status = "okay"; + }; + ++&spi0 { ++ status = "okay"; ++ ++ flash@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0>; ++ compatible = "winbond,w25q32dw", "jedec,spi-flash"; ++ spi-max-frequency = <104000000>; ++ m25p,fast-read; ++ }; ++}; ++ + /* Exported on the micro USB connector J5 through an FTDI */ + &uart0 { + status = "okay"; diff --git a/target/linux/mvebu/patches-4.14/508-cpufreq-armada-37xx-Fix-clock-leak.patch b/target/linux/mvebu/patches-4.14/508-cpufreq-armada-37xx-Fix-clock-leak.patch deleted file mode 100644 index 7479c6db21..0000000000 --- a/target/linux/mvebu/patches-4.14/508-cpufreq-armada-37xx-Fix-clock-leak.patch +++ /dev/null @@ -1,35 +0,0 @@ -From bbcc328561040292f7d6796954d478e4a2335e6f Mon Sep 17 00:00:00 2001 -From: Gregory CLEMENT -Date: Wed, 4 Apr 2018 16:44:44 +0200 -Subject: [PATCH] cpufreq: armada-37xx: Fix clock leak - -There was no clk_put() balancing the clk_get(). This commit fixes it. - -Fixes: 92ce45fb875d (cpufreq: Add DVFS support for Armada 37xx) -Cc: 4.16+ # 4.16+ -Reported-by: Thomas Petazzoni -Signed-off-by: Gregory CLEMENT -Acked-by: Viresh Kumar -Signed-off-by: Rafael J. Wysocki ---- - drivers/cpufreq/armada-37xx-cpufreq.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/cpufreq/armada-37xx-cpufreq.c -+++ b/drivers/cpufreq/armada-37xx-cpufreq.c -@@ -202,6 +202,7 @@ static int __init armada37xx_cpufreq_dri - cur_frequency = clk_get_rate(clk); - if (!cur_frequency) { - dev_err(cpu_dev, "Failed to get clock rate for CPU\n"); -+ clk_put(clk); - return -EINVAL; - } - -@@ -210,6 +211,7 @@ static int __init armada37xx_cpufreq_dri - return -EINVAL; - - armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider); -+ clk_put(clk); - - for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR; - load_lvl++) { diff --git a/target/linux/mvebu/patches-4.14/509-cpufreq-armada-37xx-Fix-clock-leak.patch b/target/linux/mvebu/patches-4.14/509-cpufreq-armada-37xx-Fix-clock-leak.patch new file mode 100644 index 0000000000..7479c6db21 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/509-cpufreq-armada-37xx-Fix-clock-leak.patch @@ -0,0 +1,35 @@ +From bbcc328561040292f7d6796954d478e4a2335e6f Mon Sep 17 00:00:00 2001 +From: Gregory CLEMENT +Date: Wed, 4 Apr 2018 16:44:44 +0200 +Subject: [PATCH] cpufreq: armada-37xx: Fix clock leak + +There was no clk_put() balancing the clk_get(). This commit fixes it. + +Fixes: 92ce45fb875d (cpufreq: Add DVFS support for Armada 37xx) +Cc: 4.16+ # 4.16+ +Reported-by: Thomas Petazzoni +Signed-off-by: Gregory CLEMENT +Acked-by: Viresh Kumar +Signed-off-by: Rafael J. Wysocki +--- + drivers/cpufreq/armada-37xx-cpufreq.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/cpufreq/armada-37xx-cpufreq.c ++++ b/drivers/cpufreq/armada-37xx-cpufreq.c +@@ -202,6 +202,7 @@ static int __init armada37xx_cpufreq_dri + cur_frequency = clk_get_rate(clk); + if (!cur_frequency) { + dev_err(cpu_dev, "Failed to get clock rate for CPU\n"); ++ clk_put(clk); + return -EINVAL; + } + +@@ -210,6 +211,7 @@ static int __init armada37xx_cpufreq_dri + return -EINVAL; + + armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider); ++ clk_put(clk); + + for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR; + load_lvl++) { diff --git a/target/linux/mvebu/patches-4.14/521-arm64-dts-armada-3720-espressobin-wire-up-spi-flash.patch b/target/linux/mvebu/patches-4.14/521-arm64-dts-armada-3720-espressobin-wire-up-spi-flash.patch deleted file mode 100644 index fb80db7e89..0000000000 --- a/target/linux/mvebu/patches-4.14/521-arm64-dts-armada-3720-espressobin-wire-up-spi-flash.patch +++ /dev/null @@ -1,45 +0,0 @@ -From bffed3d4abcd32ba6d492a9bd7ebe81dc92eaa9a Mon Sep 17 00:00:00 2001 -From: Ellie Reeves -Date: Sun, 25 Mar 2018 21:57:36 +0200 -Subject: [PATCH] arm64: dts: armada-3720-espressobin: wire up spi flash -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This is the storage the machine boots from by default. The partitioning -is taken from the U-Boot that is shipped with the board. There is some -more space on the flash that isn't used. - -Tested-by: Gregory CLEMENT -Signed-off-by: Ellie Reeves -Signed-off-by: Uwe Kleine-König -Signed-off-by: Gregory CLEMENT - -[drop partitions, not every U-Boot has same layout] -Signed-off-by: Tomasz Maciej Nowak ---- - .../dts/marvell/armada-3720-espressobin.dts | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - ---- a/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts -+++ b/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts -@@ -96,6 +96,19 @@ - status = "okay"; - }; - -+&spi0 { -+ status = "okay"; -+ -+ flash@0 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <0>; -+ compatible = "winbond,w25q32dw", "jedec,spi-flash"; -+ spi-max-frequency = <104000000>; -+ m25p,fast-read; -+ }; -+}; -+ - /* Exported on the micro USB connector J5 through an FTDI */ - &uart0 { - status = "okay";