diff options
Diffstat (limited to 'drivers')
38 files changed, 1710 insertions, 1618 deletions
diff --git a/drivers/bios_emulator/atibios.c b/drivers/bios_emulator/atibios.c index d544ffb5ffb..e992a1aa822 100644 --- a/drivers/bios_emulator/atibios.c +++ b/drivers/bios_emulator/atibios.c @@ -99,7 +99,7 @@ static int atibios_debug_mode(BE_VGAInfo *vga_info, RMREGS *regs, regs->e.edi = buffer_adr; info = buffer; memset(info, '\0', sizeof(*info)); - strcpy(info->signature, "VBE2"); + memcpy(info->signature, "VBE2", 4); BE_int86(0x10, regs, regs); if (regs->e.eax != 0x4f) { debug("VESA_GET_INFO: error %x\n", regs->e.eax); diff --git a/drivers/bios_emulator/x86emu/ops2.c b/drivers/bios_emulator/x86emu/ops2.c index 1ff27b2af95..29a166f7fe9 100644 --- a/drivers/bios_emulator/x86emu/ops2.c +++ b/drivers/bios_emulator/x86emu/ops2.c @@ -66,7 +66,7 @@ void x86emuOp2_illegal_op( END_OF_INSTR(); } -#define xorl(a,b) ((a) && !(b)) || (!(a) && (b)) +#define xorl(a, b) (((a) && !(b)) || (!(a) && (b))) /**************************************************************************** REMARKS: diff --git a/drivers/clk/altera/clk-n5x.c b/drivers/clk/altera/clk-n5x.c index 09db250ab6d..9e4e7a1d908 100644 --- a/drivers/clk/altera/clk-n5x.c +++ b/drivers/clk/altera/clk-n5x.c @@ -386,8 +386,8 @@ static u32 clk_get_emac_clk_hz(struct socfpga_clk_plat *plat, u32 emac_id) } else { clock /= 1 + ((CM_REG_READL(plat, CLKMGR_PERPLL_PLLOUTDIV) & - CLKMGR_PLLOUTDIV_C3CNT_MASK >> - CLKMGR_PLLOUTDIV_C3CNT_OFFSET)); + CLKMGR_PLLOUTDIV_C3CNT_MASK) >> + CLKMGR_PLLOUTDIV_C3CNT_OFFSET); } break; diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 6cca861f81c..96cc2bc3abc 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_AT91_UTMI) += clk-utmi.o obj-$(CONFIG_AT91_SAM9X60_PLL) += clk-sam9x60-pll.o obj-$(CONFIG_AT91_SAM9X60_USB) += clk-sam9x60-usb.o obj-$(CONFIG_SAMA7G5) += sama7g5.o +obj-$(CONFIG_SAMA7D65) += sama7d65.o obj-$(CONFIG_SAM9X60) += sam9x60.o obj-$(CONFIG_SAM9X7) += sam9x7.o else diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c index d28775d64d3..cdc5271fa83 100644 --- a/drivers/clk/at91/clk-master.c +++ b/drivers/clk/at91/clk-master.c @@ -37,7 +37,7 @@ #define PMC_MCR_ID(x) ((x) & PMC_MCR_ID_MSK) -#define MASTER_MAX_ID 4 +#define MASTER_MAX_ID 10 struct clk_master { void __iomem *base; diff --git a/drivers/clk/at91/clk-sam9x60-pll.c b/drivers/clk/at91/clk-sam9x60-pll.c index df8172bccac..65be2775ac3 100644 --- a/drivers/clk/at91/clk-sam9x60-pll.c +++ b/drivers/clk/at91/clk-sam9x60-pll.c @@ -32,7 +32,7 @@ #define UPLL_DIV 2 #define PLL_MUL_MAX (FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, UINT_MAX) + 1) -#define PLL_MAX_ID 7 +#define PLL_MAX_ID 8 struct sam9x60_pll { void __iomem *base; diff --git a/drivers/clk/at91/sama7d65.c b/drivers/clk/at91/sama7d65.c new file mode 100644 index 00000000000..8d2c25e6fa9 --- /dev/null +++ b/drivers/clk/at91/sama7d65.c @@ -0,0 +1,1451 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * SAMA7D65 PMC clock support. + * + * Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + * + * Author: Ryan Wanner <Ryan.Wanner@microchip.com> + * + */ + +#include <clk-uclass.h> +#include <dm.h> +#include <dt-bindings/clock/at91.h> +#include <linux/clk-provider.h> + +#include "pmc.h" + +/** + * Clock identifiers to be used in conjunction with macros like + * AT91_TO_CLK_ID() + * + * @ID_MD_SLCK: TD slow clock identifier + * @ID_TD_SLCK: MD slow clock identifier + * @ID_MAIN_XTAL: Main Xtal clock identifier + * @ID_MAIN_RC: Main RC clock identifier + * @ID_MAIN_RC_OSC: Main RC Oscillator clock identifier + * @ID_MAIN_OSC: Main Oscillator clock identifier + * @ID_MAINCK: MAINCK clock identifier + * @ID_PLL_CPU_FRAC: CPU PLL fractional clock identifier + * @ID_PLL_CPU_DIV: CPU PLL divider clock identifier + * @ID_PLL_SYS_FRAC: SYS PLL fractional clock identifier + * @ID_PLL_SYS_DIV: SYS PLL divider clock identifier + * @ID_PLL_DDR_FRAC: DDR PLL fractional clock identifier + * @ID_PLL_DDR_DIV: DDR PLL divider clock identifier + * @ID_PLL_GPU_FRAC: GPU PLL fractional clock identifier + * @ID_PLL_GPU_DIV: GPU PLL divider clock identifier + * @ID_PLL_BAUD_FRAC: Baud PLL fractional clock identifier + * @ID_PLL_BAUD_DIV: Baud PLL divider clock identifier + * @ID_PLL_AUDIO_FRAC: Audio PLL fractional clock identifier + * @ID_PLL_AUDIO_DIVPMC: Audio PLL PMC divider clock identifier + * @ID_PLL_AUDIO_DIVIO: Audio PLL IO divider clock identifier + * @ID_PLL_ETH_FRAC: Ethernet PLL fractional clock identifier + * @ID_PLL_ETH_DIV: Ethernet PLL divider clock identifier + * @ID_PLL_LVDS_FRAC: LVDS PLL fractional clock identifier + * @ID_PLL_LVDS_DIV: LVDS PLL divider clock identifier + * @ID_PLL_USB_FRAC: USB PLL fractional clock identifier + * @ID_PLL_USB_DIV: USB PLL divider clock identifier + + * @ID_MCK0_PRES: MCK0 PRES clock identifier + * @ID_MCK0_DIV: MCK0 DIV clock identifier + * @ID_MCK1: MCK1 clock identifier + * @ID_MCK2: MCK2 clock identifier + * @ID_MCK3: MCK3 clock identifier + * @ID_MCK4: MCK4 clock identifier + + * @ID_UTMI: UTMI clock identifier + + * @ID_PROG0: Programmable 0 clock identifier + * @ID_PROG1: Programmable 1 clock identifier + * @ID_PROG2: Programmable 2 clock identifier + * @ID_PROG3: Programmable 3 clock identifier + * @ID_PROG4: Programmable 4 clock identifier + * @ID_PROG5: Programmable 5 clock identifier + * @ID_PROG6: Programmable 6 clock identifier + * @ID_PROG7: Programmable 7 clock identifier + + * @ID_PCK0: System clock 0 clock identifier + * @ID_PCK1: System clock 1 clock identifier + * @ID_PCK2: System clock 2 clock identifier + * @ID_PCK3: System clock 3 clock identifier + * @ID_PCK4: System clock 4 clock identifier + * @ID_PCK5: System clock 5 clock identifier + * @ID_PCK6: System clock 6 clock identifier + * @ID_PCK7: System clock 7 clock identifier + */ +enum pmc_clk_ids { + ID_MD_SLCK = 0, + ID_TD_SLCK = 1, + ID_MAIN_XTAL = 2, + ID_MAIN_RC = 3, + ID_MAIN_RC_OSC = 4, + ID_MAIN_OSC = 5, + ID_MAINCK = 6, + + ID_PLL_CPU_FRAC = 7, + ID_PLL_CPU_DIV = 8, + ID_PLL_SYS_FRAC = 9, + ID_PLL_SYS_DIV = 10, + ID_PLL_DDR_FRAC = 11, + ID_PLL_DDR_DIV = 12, + ID_PLL_GPU_FRAC = 13, + ID_PLL_GPU_DIV = 14, + ID_PLL_BAUD_FRAC = 15, + ID_PLL_BAUD_DIV = 16, + ID_PLL_AUDIO_FRAC = 17, + ID_PLL_AUDIO_DIVPMC = 18, + ID_PLL_AUDIO_DIVIO = 19, + ID_PLL_ETH_FRAC = 20, + ID_PLL_ETH_DIV = 21, + ID_PLL_LVDS_FRAC = 22, + ID_PLL_LVDS_DIV = 23, + ID_PLL_USB_FRAC = 24, + ID_PLL_USB_DIV = 25, + + ID_MCK0_DIV = 26, + ID_MCK1 = 27, + ID_MCK2 = 28, + ID_MCK3 = 29, + ID_MCK4 = 30, + ID_MCK5 = 31, + ID_MCK6 = 32, + ID_MCK7 = 33, + ID_MCK8 = 34, + ID_MCK9 = 35, + + ID_UTMI = 36, + + ID_PROG0 = 37, + ID_PROG1 = 38, + ID_PROG2 = 39, + ID_PROG3 = 40, + ID_PROG4 = 41, + ID_PROG5 = 42, + ID_PROG6 = 43, + ID_PROG7 = 44, + + ID_PCK0 = 45, + ID_PCK1 = 46, + ID_PCK2 = 47, + ID_PCK3 = 48, + ID_PCK4 = 49, + ID_PCK5 = 50, + ID_PCK6 = 51, + ID_PCK7 = 52, + + ID_MCK0_PRES = 53, + + ID_MAX, +}; + +/** + * PLL type identifiers + * @PLL_TYPE_FRAC: fractional PLL identifier + * @PLL_TYPE_DIV: divider PLL identifier + */ +enum pll_type { + PLL_TYPE_FRAC, + PLL_TYPE_DIV, +}; + +/* Clock names used as parents for multiple clocks. */ +static const char *clk_names[] = { + [ID_MAIN_RC] = "main_rc", + [ID_MAIN_RC_OSC] = "main_rc_osc", + [ID_MAIN_OSC] = "main_osc", + [ID_MAINCK] = "mainck", + [ID_PLL_CPU_DIV] = "cpupll_divpmcck", + [ID_PLL_SYS_DIV] = "syspll_divpmcck", + [ID_PLL_DDR_DIV] = "ddrpll_divpmcck", + [ID_PLL_GPU_DIV] = "gpupll_divpmcck", + [ID_PLL_BAUD_DIV] = "baudpll_divpmcck", + [ID_PLL_AUDIO_DIVPMC] = "audiopll_divpmcck", + [ID_PLL_AUDIO_DIVIO] = "audiopll_diviock", + [ID_PLL_ETH_DIV] = "ethpll_divpmcck", + [ID_PLL_LVDS_DIV] = "lvdspll_divpmcck", + [ID_PLL_USB_DIV] = "usbpll_divpmcck", + [ID_MCK0_DIV] = "mck0_div", + [ID_MCK0_PRES] = "mck0_pres", +}; + +/* Fractional PLL output range. */ +static const struct clk_range pll_outputs[] = { + { .min = 2343750, .max = 1200000000 }, +}; + +/* Fractional PLL core output range. */ +static const struct clk_range core_outputs[] = { + { .min = 600000000, .max = 1200000000 }, +}; + +/* PLL characteristics. */ +static const struct clk_pll_characteristics pll_characteristics = { + .input = { .min = 12000000, .max = 50000000 }, + .num_output = ARRAY_SIZE(pll_outputs), + .output = pll_outputs, + .core_output = core_outputs, +}; + +/* Layout for fractional PLLs. */ +static const struct clk_pll_layout pll_layout_frac = { + .mul_mask = GENMASK(31, 24), + .frac_mask = GENMASK(21, 0), + .mul_shift = 24, + .frac_shift = 0, +}; + +/* Layout for DIVPMC dividers. */ +static const struct clk_pll_layout pll_layout_divpmc = { + .div_mask = GENMASK(7, 0), + .endiv_mask = BIT(29), + .div_shift = 0, + .endiv_shift = 29, +}; + +/* Layout for DIVIO dividers. */ +static const struct clk_pll_layout pll_layout_divio = { + .div_mask = GENMASK(19, 12), + .endiv_mask = BIT(30), + .div_shift = 12, + .endiv_shift = 30, +}; + +/* MCK0 characteristics. */ +static const struct clk_master_characteristics mck0_characteristics = { + .output = { .min = 140000000, .max = 200000000 }, + .divisors = { 1, 2, 4, 3, 5 }, + .have_div3_pres = 1, +}; + +/* MCK0 layout. */ +static const struct clk_master_layout mck0_layout = { + .mask = 0x773, + .pres_shift = 4, + .offset = 0x28, +}; + +/* Programmable clock layout. */ +static const struct clk_programmable_layout programmable_layout = { + .pres_mask = 0xff, + .pres_shift = 8, + .css_mask = 0x1f, + .have_slck_mck = 0, + .is_pres_direct = 1, +}; + +/* Peripheral clock layout. */ +static const struct clk_pcr_layout sama7d65_pcr_layout = { + .offset = 0x88, + .cmd = BIT(31), + .gckcss_mask = GENMASK(12, 8), + .pid_mask = GENMASK(6, 0), +}; + +/** + * PLL clocks description + * @n: clock name + * @p: clock parent + * @l: clock layout + * @t: clock type + * @c: true if clock is critical and cannot be disabled + * @id: clock id corresponding to PLL driver + * @cid: clock id corresponding to clock subsystem + */ +static const struct { + const char *n; + const char *p; + const struct clk_pll_layout *l; + u8 t; + u8 c; + u8 id; + u8 cid; +} sama7d65_plls[] = { + { + .n = "cpupll_fracck", + .p = "mainck", + .l = &pll_layout_frac, + .t = PLL_TYPE_FRAC, + .c = 1, + .id = 0, + .cid = ID_PLL_CPU_FRAC, + }, + + { + .n = "cpupll_divpmcck", + .p = "cpupll_fracck", + .l = &pll_layout_divpmc, + .t = PLL_TYPE_DIV, + .c = 1, + .id = 0, + .cid = ID_PLL_CPU_DIV, + }, + + { + .n = "syspll_fracck", + .p = "mainck", + .l = &pll_layout_frac, + .t = PLL_TYPE_FRAC, + .c = 1, + .id = 1, + .cid = ID_PLL_SYS_FRAC, + }, + + { + .n = "syspll_divpmcck", + .p = "syspll_fracck", + .l = &pll_layout_divpmc, + .t = PLL_TYPE_DIV, + .c = 1, + .id = 1, + .cid = ID_PLL_SYS_DIV, + }, + + { + .n = "ddrpll_fracck", + .p = "mainck", + .l = &pll_layout_frac, + .t = PLL_TYPE_FRAC, + .c = 1, + .id = 2, + .cid = ID_PLL_DDR_FRAC, + }, + + { + .n = "ddrpll_divpmcck", + .p = "ddrpll_fracck", + .l = &pll_layout_divpmc, + .t = PLL_TYPE_DIV, + .c = 1, + .id = 2, + .cid = ID_PLL_DDR_DIV, + }, + + { + .n = "gpupll_fracck", + .p = "mainck", + .l = &pll_layout_frac, + .t = PLL_TYPE_FRAC, + .id = 3, + .cid = ID_PLL_GPU_FRAC, + }, + + { + .n = "gpupll_divpmcck", + .p = "gpupll_fracck", + .l = &pll_layout_divpmc, + .t = PLL_TYPE_DIV, + .id = 3, + .cid = ID_PLL_GPU_DIV + }, + + { + .n = "baudpll_fracck", + .p = "mainck", + .l = &pll_layout_frac, + .t = PLL_TYPE_FRAC, + .id = 4, + .cid = ID_PLL_BAUD_FRAC, + }, + + { + .n = "baudpll_divpmcck", + .p = "baudpll_fracck", + .l = &pll_layout_divpmc, + .t = PLL_TYPE_DIV, + .id = 4, + .cid = ID_PLL_BAUD_DIV, + }, + + { + .n = "audiopll_fracck", + .p = "main_osc", + .l = &pll_layout_frac, + .t = PLL_TYPE_FRAC, + .id = 5, + .cid = ID_PLL_AUDIO_FRAC, + }, + + { + .n = "audiopll_divpmcck", + .p = "audiopll_fracck", + .l = &pll_layout_divpmc, + .t = PLL_TYPE_DIV, + .id = 5, + .cid = ID_PLL_AUDIO_DIVPMC, + }, + + { + .n = "audiopll_diviock", + .p = "audiopll_fracck", + .l = &pll_layout_divio, + .t = PLL_TYPE_DIV, + .id = 5, + .cid = ID_PLL_AUDIO_DIVIO, + }, + + { + .n = "ethpll_fracck", + .p = "main_osc", + .l = &pll_layout_frac, + .t = PLL_TYPE_FRAC, + .id = 6, + .cid = ID_PLL_ETH_FRAC, + }, + + { + .n = "ethpll_divpmcck", + .p = "ethpll_fracck", + .l = &pll_layout_divpmc, + .t = PLL_TYPE_DIV, + .id = 6, + .cid = ID_PLL_ETH_DIV, + }, + { + .n = "lvdspll_fracck", + .p = "main_osc", + .l = &pll_layout_frac, + .t = PLL_TYPE_FRAC, + .id = 7, + .cid = ID_PLL_LVDS_FRAC, + }, + { + .n = "lvdspll_divpmcck", + .p = "lvdspll_fracck", + .l = &pll_layout_divpmc, + .t = PLL_TYPE_DIV, + .id = 7, + .cid = ID_PLL_LVDS_DIV, + }, + { + .n = "usbpll_fracck", + .p = "main_osc", + .l = &pll_layout_frac, + .t = PLL_TYPE_FRAC, + .id = 8, + .cid = ID_PLL_USB_FRAC, + }, + { + .n = "usbpll_divmpcck", + .p = "usbpll_fracck", + .l = &pll_layout_divpmc, + .t = PLL_TYPE_DIV, + .id = 8, + .cid = ID_PLL_USB_DIV, + }, +}; + +/** + * Master clock (MCK[1..9]) description + * @n: clock name + * @ep: extra parents names array + * @ep_chg_chg_id: index in parents array that specifies the changeable + * parent + * @ep_count: extra parents count + * @ep_mux_table: mux table for extra parents + * @ep_clk_mux_table: mux table to deal with subsystem clock ids + * @id: clock id corresponding to MCK driver + * @cid: clock id corresponding to clock subsystem + * @c: true if clock is critical and cannot be disabled + */ +static const struct { + const char *n; + const char *ep[4]; + u8 ep_count; + u8 ep_mux_table[4]; + u8 ep_clk_mux_table[4]; + u8 id; + u8 cid; + u8 c; +} sama7d65_mckx[] = { + { + .n = "mck1", + .id = 1, + .cid = ID_MCK1, + .ep = { "syspll_divpmcck", }, + .ep_mux_table = { 5, }, + .ep_clk_mux_table = { ID_PLL_SYS_DIV, }, + .ep_count = 1, + .c = 1, + }, + + { + .n = "mck2", + .id = 2, + .cid = ID_MCK2, + .ep = { "syspll_divpmcck", "ddrpll_divpmcck", }, + .ep_mux_table = { 5, 6, }, + .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_DDR_DIV, }, + .ep_count = 2, + .c = 1, + }, + + { + .n = "mck3", + .id = 3, + .cid = ID_MCK3, + .ep = { "syspll_divpmcck", "ddrpll_divpmcck", }, + .ep_mux_table = { 5, 6, }, + .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_DDR_DIV, }, + .ep_count = 2, + }, + + { + .n = "mck4", + .id = 4, + .cid = ID_MCK4, + .ep = { "syspll_divpmcck", }, + .ep_mux_table = { 5, }, + .ep_clk_mux_table = { ID_PLL_SYS_DIV, }, + .ep_count = 1, + .c = 1, + }, + + { + .n = "mck5", + .id = 5, + .cid = ID_MCK5, + .ep = { "syspll_divpmcck", }, + .ep_mux_table = { 5, }, + .ep_clk_mux_table = { ID_PLL_SYS_DIV, }, + .ep_count = 1, + }, + + { + .n = "mck6", + .id = 6, + .cid = ID_MCK6, + .ep = { "syspll_divpmcck", }, + .ep_mux_table = { 5, }, + .ep_clk_mux_table = { ID_PLL_SYS_DIV, }, + .ep_count = 1, + .c = 1, + }, + + { + .n = "mck7", + .id = 7, + .cid = ID_MCK7, + .ep = { "syspll_divpmcck", }, + .ep_mux_table = { 5, }, + .ep_clk_mux_table = { ID_PLL_SYS_DIV, }, + .ep_count = 1, + .c = 1, + }, + + { + .n = "mck8", + .id = 8, + .cid = ID_MCK8, + .ep = { "syspll_divpmcck", }, + .ep_mux_table = { 5, }, + .ep_clk_mux_table = { ID_PLL_SYS_DIV, }, + .ep_count = 1, + .c = 1, + }, + + { + .n = "mck9", + .id = 9, + .cid = ID_MCK9, + .ep = { "syspll_divpmcck", }, + .ep_mux_table = { 5, }, + .ep_clk_mux_table = { ID_PLL_SYS_DIV, }, + .ep_count = 1, + }, + +}; + +/** + * Programmable clock description + * @n: clock name + * @cid: clock id corresponding to clock subsystem + */ +static const struct { + const char *n; + u8 cid; +} sama7d65_prog[] = { + { .n = "prog0", .cid = ID_PROG0, }, + { .n = "prog1", .cid = ID_PROG1, }, + { .n = "prog2", .cid = ID_PROG2, }, + { .n = "prog3", .cid = ID_PROG3, }, + { .n = "prog4", .cid = ID_PROG4, }, + { .n = "prog5", .cid = ID_PROG5, }, + { .n = "prog6", .cid = ID_PROG6, }, + { .n = "prog7", .cid = ID_PROG7, }, +}; + +/* Mux table for programmable clocks. */ +static u32 sama7d65_prog_mux_table[] = { 0, 1, 2, 3, 5, 7, 8, 9, 10, 12, }; + +/** + * System clock description + * @n: clock name + * @p: parent clock name + * @id: clock id corresponding to system clock driver + * @cid: clock id corresponding to clock subsystem + */ +static const struct { + const char *n; + const char *p; + u8 id; + u8 cid; +} sama7d65_systemck[] = { + { .n = "pck0", .p = "prog0", .id = 8, .cid = ID_PCK0, }, + { .n = "pck1", .p = "prog1", .id = 9, .cid = ID_PCK1, }, + { .n = "pck2", .p = "prog2", .id = 10, .cid = ID_PCK2, }, + { .n = "pck3", .p = "prog3", .id = 11, .cid = ID_PCK3, }, + { .n = "pck4", .p = "prog4", .id = 12, .cid = ID_PCK4, }, + { .n = "pck5", .p = "prog5", .id = 13, .cid = ID_PCK5, }, + { .n = "pck6", .p = "prog6", .id = 14, .cid = ID_PCK6, }, + { .n = "pck7", .p = "prog7", .id = 15, .cid = ID_PCK7, }, +}; + +/** + * Peripheral clock description + * @n: clock name + * @p: clock parent name + * @r: clock range values + * @id: clock id + */ +static const struct { + const char *n; + const char *p; + struct clk_range r; + u8 id; +} sama7d65_periphck[] = { + { .n = "pioA_clk", .p = "mck0_div", .id = 10, }, + { .n = "sfr_clk", .p = "mck7", .id = 18, }, + { .n = "hsmc_clk", .p = "mck5", .id = 20, }, + { .n = "xdmac0_clk", .p = "mck6", .id = 21, }, + { .n = "xdmac1_clk", .p = "mck6", .id = 22, }, + { .n = "xdmac2_clk", .p = "mck1", .id = 23, }, + { .n = "acc_clk", .p = "mck7", .id = 24, }, + { .n = "aes_clk", .p = "mck6", .id = 26, }, + { .n = "tzaesbasc_clk", .p = "mck8", .id = 27, }, + { .n = "asrc_clk", .p = "mck9", .id = 29, .r = { .max = 200000000, }, }, + { .n = "cpkcc_clk", .p = "mck0_div", .id = 30, }, + { .n = "eic_clk", .p = "mck7", .id = 33, }, + { .n = "flex0_clk", .p = "mck7", .id = 34, }, + { .n = "flex1_clk", .p = "mck7", .id = 35, }, + { .n = "flex2_clk", .p = "mck7", .id = 36, }, + { .n = "flex3_clk", .p = "mck7", .id = 37, }, + { .n = "flex4_clk", .p = "mck8", .id = 38, }, + { .n = "flex5_clk", .p = "mck8", .id = 39, }, + { .n = "flex6_clk", .p = "mck8", .id = 40, }, + { .n = "flex7_clk", .p = "mck8", .id = 41, }, + { .n = "flex8_clk", .p = "mck9", .id = 42, }, + { .n = "flex9_clk", .p = "mck9", .id = 43, }, + { .n = "flex10_clk", .p = "mck9", .id = 44, }, + { .n = "gmac0_clk", .p = "mck6", .id = 46, }, + { .n = "gmac1_clk", .p = "mck6", .id = 47, }, + { .n = "gmac0_tsu_clk", .p = "mck1", .id = 49, }, + { .n = "gmac1_tsu_clk", .p = "mck1", .id = 50, }, + { .n = "icm_clk", .p = "mck5", .id = 53, }, + { .n = "i2smcc0_clk", .p = "mck9", .id = 54, .r = { .max = 200000000, }, }, + { .n = "i2smcc1_clk", .p = "mck9", .id = 55, .r = { .max = 200000000, }, }, + { .n = "matrix_clk", .p = "mck5", .id = 57, }, + { .n = "mcan0_clk", .p = "mck5", .id = 58, .r = { .max = 200000000, }, }, + { .n = "mcan1_clk", .p = "mck5", .id = 59, .r = { .max = 200000000, }, }, + { .n = "mcan2_clk", .p = "mck5", .id = 60, .r = { .max = 200000000, }, }, + { .n = "mcan3_clk", .p = "mck5", .id = 61, .r = { .max = 200000000, }, }, + { .n = "mcan4_clk", .p = "mck5", .id = 62, .r = { .max = 200000000, }, }, + { .n = "pdmc0_clk", .p = "mck9", .id = 64, .r = { .max = 200000000, }, }, + { .n = "pdmc1_clk", .p = "mck9", .id = 65, .r = { .max = 200000000, }, }, + { .n = "pit64b0_clk", .p = "mck7", .id = 66, }, + { .n = "pit64b1_clk", .p = "mck7", .id = 67, }, + { .n = "pit64b2_clk", .p = "mck7", .id = 68, }, + { .n = "pit64b3_clk", .p = "mck8", .id = 69, }, + { .n = "pit64b4_clk", .p = "mck8", .id = 70, }, + { .n = "pit64b5_clk", .p = "mck8", .id = 71, }, + { .n = "pwm_clk", .p = "mck7", .id = 72, }, + { .n = "qspi0_clk", .p = "mck5", .id = 73, }, + { .n = "qspi1_clk", .p = "mck5", .id = 74, }, + { .n = "sdmmc0_clk", .p = "mck1", .id = 75, }, + { .n = "sdmmc1_clk", .p = "mck1", .id = 76, }, + { .n = "sdmmc2_clk", .p = "mck1", .id = 77, }, + { .n = "sha_clk", .p = "mck6", .id = 78, }, + { .n = "spdifrx_clk", .p = "mck9", .id = 79, .r = { .max = 200000000, }, }, + { .n = "spdiftx_clk", .p = "mck9", .id = 80, .r = { .max = 200000000, }, }, + { .n = "ssc0_clk", .p = "mck7", .id = 81, .r = { .max = 200000000, }, }, + { .n = "ssc1_clk", .p = "mck8", .id = 82, .r = { .max = 200000000, }, }, + { .n = "tcb0_ch0_clk", .p = "mck8", .id = 83, .r = { .max = 200000000, }, }, + { .n = "tcb0_ch1_clk", .p = "mck8", .id = 84, .r = { .max = 200000000, }, }, + { .n = "tcb0_ch2_clk", .p = "mck8", .id = 85, .r = { .max = 200000000, }, }, + { .n = "tcb1_ch0_clk", .p = "mck5", .id = 86, .r = { .max = 200000000, }, }, + { .n = "tcb1_ch1_clk", .p = "mck5", .id = 87, .r = { .max = 200000000, }, }, + { .n = "tcb1_ch2_clk", .p = "mck5", .id = 88, .r = { .max = 200000000, }, }, + { .n = "tcpca_clk", .p = "mck5", .id = 89, }, + { .n = "tcpcb_clk", .p = "mck5", .id = 90, }, + { .n = "tdes_clk", .p = "mck6", .id = 91, }, + { .n = "trng_clk", .p = "mck6", .id = 92, }, + { .n = "udphsa_clk", .p = "mck5", .id = 99, }, + { .n = "udphsb_clk", .p = "mck5", .id = 100, }, + { .n = "uhphs_clk", .p = "mck5", .id = 101, }, +}; + +/** + * Generic clock description + * @n: clock name + * @ep: extra parents names + * @ep_mux_table: extra parents mux table + * @ep_clk_mux_table: extra parents clock mux table (for CCF) + * @r: clock output range + * @ep_count: extra parents count + * @id: clock id + */ +static const struct { + const char *n; + const char *ep[8]; + const char ep_mux_table[8]; + const char ep_clk_mux_table[8]; + struct clk_range r; + u8 ep_count; + u8 id; +} sama7d65_gck[] = { + { + .n = "adc_gclk", + .id = 25, + .r = { .max = 100000000, }, + .ep = { "baudpll_divpmcck", "audiopll_divpmcck", }, + .ep_mux_table = { 8, 9, }, + .ep_clk_mux_table = { ID_PLL_BAUD_DIV, ID_PLL_AUDIO_DIVPMC, }, + .ep_count = 2, + }, + + { + .n = "asrc_gclk", + .id = 29, + .r = { .max = 200000000 }, + .ep = { "audiopll_divpmcck", }, + .ep_mux_table = { 9, }, + .ep_clk_mux_table = { ID_PLL_AUDIO_DIVPMC, }, + .ep_count = 1, + }, + + { + .n = "flex0_gclk", + .id = 34, + .r = { .max = 34000000 }, + .ep = {"baudpll_divpmcck", }, + .ep_mux_table = { 8, }, + .ep_clk_mux_table = {ID_PLL_BAUD_DIV, }, + .ep_count = 1, + }, + + { + .n = "flex1_gclk", + .id = 35, + .r = { .max = 34000000 }, + .ep = {"baudpll_divpmcck", }, + .ep_mux_table = { 8, }, + .ep_clk_mux_table = { ID_PLL_BAUD_DIV, }, + .ep_count = 1, + }, + + { + .n = "flex2_gclk", + .id = 36, + .r = { .max = 34000000 }, + .ep = { "baudpll_divpmcck", }, + .ep_mux_table = { 8,}, + .ep_clk_mux_table = {ID_PLL_BAUD_DIV, }, + .ep_count = 1, + }, + + { + .n = "flex3_gclk", + .id = 37, + .r = { .max = 34000000 }, + .ep = {"baudpll_divpmcck", }, + .ep_mux_table = { 8,}, + .ep_clk_mux_table = { ID_PLL_BAUD_DIV, }, + .ep_count = 1, + }, + + { + .n = "flex4_gclk", + .id = 38, + .r = { .max = 34000000 }, + .ep = {"baudpll_divpmcck", }, + .ep_mux_table = { 8, }, + .ep_clk_mux_table = { ID_PLL_BAUD_DIV, }, + .ep_count = 1, + }, + + { + .n = "flex5_gclk", + .id = 39, + .r = { .max = 34000000 }, + .ep = { "baudpll_divpmcck", }, + .ep_mux_table = { 8, }, + .ep_clk_mux_table = {ID_PLL_BAUD_DIV, }, + .ep_count = 1, + }, + + { + .n = "flex6_gclk", + .id = 40, + .r = { .max = 34000000 }, + .ep = { "baudpll_divpmcck", }, + .ep_mux_table = { 8, }, + .ep_clk_mux_table = { ID_PLL_BAUD_DIV, }, + .ep_count = 1, + }, + + { + .n = "flex7_gclk", + .id = 41, + .r = { .max = 34000000 }, + .ep = { "baudpll_divpmcck", }, + .ep_mux_table = { 8, }, + .ep_clk_mux_table = {ID_PLL_BAUD_DIV, }, + .ep_count = 1, + }, + + { + .n = "flex8_gclk", + .id = 42, + .r = { .max = 34000000 }, + .ep = { "baudpll_divpmcck", }, + .ep_mux_table = { 8,}, + .ep_clk_mux_table = { ID_PLL_BAUD_DIV, }, + .ep_count = 1, + }, + + { + .n = "flex9_gclk", + .id = 43, + .r = { .max = 34000000 }, + .ep = { "baudpll_divpmcck", }, + .ep_mux_table = { 8,}, + .ep_clk_mux_table = {ID_PLL_BAUD_DIV, }, + .ep_count = 1, + }, + + { + .n = "flex10_gclk", + .id = 44, + .r = { .max = 34000000 }, + .ep = { "baudpll_divpmcck", }, + .ep_mux_table = { 8,}, + .ep_clk_mux_table = {ID_PLL_BAUD_DIV, }, + .ep_count = 1, + }, + + { + .n = "gmac0_gclk", + .id = 46, + .r = { .max = 125000000}, + .ep = { "ethpll_divpmcck", }, + .ep_clk_mux_table = { ID_PLL_ETH_DIV, }, + .ep_mux_table = { 10, }, + .ep_count = 1, + }, + + { + .n = "gmac1_gclk", + .id = 47, + .r = { .max = 125000000}, + .ep = { "ethpll_divpmcck", }, + .ep_mux_table = { 10, }, + .ep_clk_mux_table = { ID_PLL_ETH_DIV, }, + .ep_count = 1, + }, + + { + .n = "gmac0_tsu_gclk", + .id = 49, + .r = { .max = 400000000 }, + .ep = { "syspll_divpmcck", "audiopll_divpmcck", "ethpll_divpmcck", }, + .ep_mux_table = { 5, 9, 10, }, + .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_AUDIO_DIVPMC, ID_PLL_ETH_DIV, }, + .ep_count = 3, + }, + + { + .n = "gmac1_tsu_gclk", + .id = 50, + .r = { .max = 400000000 }, + .ep = { "syspll_divpmcck", "audiopll_divpmcck", "ethpll_divpmcck", }, + .ep_mux_table = { 5, 9, 10, }, + .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_AUDIO_DIVPMC, ID_PLL_ETH_DIV, }, + .ep_count = 3, + }, + + { + .n = "i2smcc0_gclk", + .id = 54, + .r = { .max = 100000000 }, + .ep = { "audiopll_divpmcck", }, + .ep_mux_table = { 9, }, + .ep_clk_mux_table = {ID_PLL_AUDIO_DIVPMC, }, + .ep_count = 1, + }, + + { + .n = "i2smcc1_gclk", + .id = 55, + .r = { .max = 100000000 }, + .ep = {"audiopll_divpmcck", }, + .ep_mux_table = { 9, }, + .ep_clk_mux_table = {ID_PLL_AUDIO_DIVPMC, }, + .ep_count = 1, + }, + + { + .n = "mcan0_gclk", + .id = 58, + .r = { .max = 80000000 }, + .ep = { "usbpll_divpmcck", }, + .ep_mux_table = { 12, }, + .ep_clk_mux_table = { ID_PLL_USB_DIV }, + .ep_count = 1, + }, + + { + .n = "mcan1_gclk", + .id = 59, + .r = { .max = 80000000 }, + .ep = { "usbpll_divpmcck", }, + .ep_mux_table = { 12, }, + .ep_clk_mux_table = { ID_PLL_USB_DIV, }, + .ep_count = 1, + }, + + { + .n = "mcan2_gclk", + .id = 60, + .r = { .max = 80000000 }, + .ep = { "usbpll_divpmcck", }, + .ep_mux_table = { 12, }, + .ep_clk_mux_table = { ID_PLL_USB_DIV, }, + .ep_count = 1, + }, + + { + .n = "mcan3_gclk", + .id = 61, + .r = { .max = 80000000 }, + .ep = { "usbpll_divpmcck", }, + .ep_mux_table = { 12, }, + .ep_clk_mux_table = { ID_PLL_USB_DIV, }, + .ep_count = 1, + }, + + { + .n = "mcan4_gclk", + .id = 62, + .r = { .max = 80000000 }, + .ep = { "usbpll_divpmcck", }, + .ep_mux_table = { 12, }, + .ep_clk_mux_table = { ID_PLL_USB_DIV, }, + .ep_count = 1, + }, + + { + .n = "pdmc0_gclk", + .id = 64, + .r = { .max = 80000000 }, + .ep = { "audiopll_divpmcck", }, + .ep_mux_table = { 9, }, + .ep_clk_mux_table = { ID_PLL_AUDIO_DIVPMC, }, + .ep_count = 1, + }, + + { + .n = "pdmc1_gclk", + .id = 65, + .r = { .max = 80000000, }, + .ep = { "audiopll_divpmcck",}, + .ep_mux_table = { 9, }, + .ep_clk_mux_table = {ID_PLL_AUDIO_DIVPMC, }, + .ep_count = 1, + }, + + { + .n = "pit64b0_gclk", + .id = 66, + .r = { .max = 34000000 }, + .ep = { "baudpll_divpmcck", "audiopll_divpmcck", "ethpll_divpmcck", }, + .ep_mux_table = {8, 9, 10, }, + .ep_clk_mux_table = { ID_PLL_BAUD_DIV, ID_PLL_AUDIO_DIVPMC, + ID_PLL_ETH_DIV, }, + .ep_count = 3, + }, + + { + .n = "pit64b1_gclk", + .id = 67, + .r = { .max = 34000000 }, + .ep = { "baudpll_divpmcck", "audiopll_divpmcck", "ethpll_divpmcck", }, + .ep_mux_table = {8, 9, 10, }, + .ep_clk_mux_table = { ID_PLL_BAUD_DIV, ID_PLL_AUDIO_DIVPMC, + ID_PLL_ETH_DIV, }, + .ep_count = 3, + }, + + { + .n = "pit64b2_gclk", + .id = 68, + .r = { .max = 34000000 }, + .ep = { "baudpll_divpmcck", "audiopll_divpmcck", "ethpll_divpmcck", }, + .ep_mux_table = { 8, 9, 10, }, + .ep_clk_mux_table = {ID_PLL_BAUD_DIV, ID_PLL_AUDIO_DIVPMC, + ID_PLL_ETH_DIV, }, + .ep_count = 3, + }, + + { + .n = "pit64b3_gclk", + .id = 69, + .r = { .max = 34000000 }, + .ep = {"baudpll_divpmcck", "audiopll_divpmcck", "ethpll_divpmcck", }, + .ep_mux_table = {8, 9, 10, }, + .ep_clk_mux_table = {ID_PLL_BAUD_DIV, ID_PLL_AUDIO_DIVPMC, + ID_PLL_ETH_DIV, }, + .ep_count = 3, + }, + + { + .n = "pit64b4_gclk", + .id = 70, + .r = { .max = 34000000 }, + .ep = {"baudpll_divpmcck", "audiopll_divpmcck", "ethpll_divpmcck", }, + .ep_mux_table = {8, 9, 10, }, + .ep_clk_mux_table = {ID_PLL_BAUD_DIV, ID_PLL_AUDIO_DIVPMC, + ID_PLL_ETH_DIV, }, + .ep_count = 3, + }, + + { + .n = "pit64b5_gclk", + .id = 71, + .r = { .max = 34000000 }, + .ep = {"baudpll_divpmcck", "audiopll_divpmcck", "ethpll_divpmcck", }, + .ep_mux_table = {8, 9, 10, }, + .ep_clk_mux_table = {ID_PLL_BAUD_DIV, ID_PLL_AUDIO_DIVPMC, + ID_PLL_ETH_DIV, }, + .ep_count = 3, + }, + + { + .n = "qspi0_gclk", + .id = 73, + .r = { .max = 400000000 }, + .ep = { "syspll_divpmcck", "baudpll_divpmcck", }, + .ep_mux_table = { 5, 8, }, + .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, }, + .ep_count = 2, + }, + + { + .n = "qspi1_gclk", + .id = 74, + .r = { .max = 266000000 }, + .ep = { "syspll_divpmcck", "baudpll_divpmcck", }, + .ep_mux_table = { 5, 8, }, + .ep_clk_mux_table = { ID_PLL_SYS_DIV, ID_PLL_BAUD_DIV, }, + .ep_count = 2, + }, + + { + .n = "sdmmc0_gclk", + .id = 75, + .r = { .max = 208000000 }, + .ep = {"baudpll_divpmcck", "ethpll_divpmcck", }, + .ep_mux_table = {8, 10, }, + .ep_clk_mux_table = {ID_PLL_BAUD_DIV, ID_PLL_ETH_DIV,}, + .ep_count = 2, + }, + + { + .n = "sdmmc1_gclk", + .id = 76, + .r = { .max = 208000000 }, + .ep = { "baudpll_divpmcck", "ethpll_divpmcck", }, + .ep_mux_table = {8, 10,}, + .ep_clk_mux_table = {ID_PLL_BAUD_DIV, ID_PLL_ETH_DIV, }, + .ep_count = 2, + }, + + { + .n = "sdmmc2_gclk", + .id = 77, + .r = { .max = 208000000 }, + .ep = {"baudpll_divpmcck", "ethpll_divpmcck",}, + .ep_mux_table = {8, 10,}, + .ep_clk_mux_table = {ID_PLL_BAUD_DIV, ID_PLL_ETH_DIV,}, + .ep_count = 2, + }, + + { + .n = "spdifrx_gclk", + .id = 79, + .r = { .max = 150000000 }, + .ep = {"audiopll_divpmcck", }, + .ep_mux_table = { 9, }, + .ep_clk_mux_table = { ID_PLL_AUDIO_DIVPMC, }, + .ep_count = 1, + }, + + { + .n = "spdiftx_gclk", + .id = 80, + .r = { .max = 25000000 }, + .ep = { "audiopll_divpmcck", }, + .ep_mux_table = {9, }, + .ep_clk_mux_table = {ID_PLL_AUDIO_DIVPMC, }, + .ep_count = 1, + }, + + { + .n = "tcb0_ch0_gclk", + .id = 83, + .r = { .max = 34000000 }, + .ep = {"baudpll_divpmcck", "audiopll_divpmcck", "ethpll_divpmcck", }, + .ep_mux_table = { 8, 9, 10, }, + .ep_clk_mux_table = {ID_PLL_BAUD_DIV, ID_PLL_AUDIO_DIVPMC, + ID_PLL_ETH_DIV, }, + .ep_count = 3, + }, + + { + .n = "tcb1_ch0_gclk", + .id = 86, + .r = { .max = 67000000 }, + .ep = {"baudpll_divpmcck", "audiopll_divpmcck", "ethpll_divpmcck", }, + .ep_mux_table = {8, 9, 10, }, + .ep_clk_mux_table = {ID_PLL_BAUD_DIV, ID_PLL_AUDIO_DIVPMC, + ID_PLL_ETH_DIV, }, + .ep_count = 3, + }, + + { + .n = "DSI_gclk", + .id = 103, + .r = {.max = 27000000}, + .ep = {"syspll_divpmcck"}, + .ep_mux_table = {5}, + .ep_clk_mux_table = {ID_PLL_SYS_DIV}, + .ep_count = 1, + }, + + { + .n = "I3CC_gclk", + .id = 105, + .r = {.max = 125000000}, + .ep = {"baudpll_divpmcck", "audiopll_divpmcck", "ethpll_divpmcck", }, + .ep_mux_table = {8, 9, 10, }, + .ep_clk_mux_table = {ID_PLL_BAUD_DIV, ID_PLL_AUDIO_DIVPMC, + ID_PLL_ETH_DIV, }, + .ep_count = 3, + }, +}; + +/* Clock setup description */ +static const struct pmc_clk_setup sama7d65_clk_setup[] = { + { + .cid = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_ETH_FRAC), + .rate = 625000000, + }, + + { + .cid = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_ETH_DIV), + .rate = 625000000, + }, +}; + +#define SAMA7D65_MAX_MUX_ALLOCS (64) + +#define prepare_mux_table(_allocs, _index, _dst, _src, _num, _label) \ + do { \ + int _i; \ + if ((_index) >= SAMA7D65_MAX_MUX_ALLOCS) { \ + debug("%s(): AT91: MUX: insufficient space\n", \ + __func__); \ + goto _label; \ + } \ + (_dst) = kzalloc(sizeof(*(_dst)) * (_num), GFP_KERNEL); \ + if (!(_dst)) \ + goto _label; \ + (_allocs)[(_index)++] = (_dst); \ + for (_i = 0; _i < (_num); _i++) \ + (_dst)[_i] = (_src)[_i]; \ + } while (0) + +static int sama7d65_clk_probe(struct udevice *dev) +{ + void __iomem *base = (void *)devfdt_get_addr(dev); + unsigned int *clkmuxallocs[SAMA7D65_MAX_MUX_ALLOCS]; + unsigned int *muxallocs[SAMA7D65_MAX_MUX_ALLOCS]; + const char *p[12]; + unsigned int cm[12], m[12], *tmpclkmux, *tmpmux; + struct clk clk, *c; + bool main_osc_bypass; + int ret, muxallocindex = 0, clkmuxallocindex = 0, i, j; + + if (IS_ERR(base)) + return PTR_ERR(base); + + memset(muxallocs, 0, ARRAY_SIZE(muxallocs)); + memset(clkmuxallocs, 0, ARRAY_SIZE(clkmuxallocs)); + + ret = clk_get_by_index(dev, 0, &clk); + if (ret) + return ret; + ret = clk_get_by_id(clk.id, &c); + if (ret) + return ret; + clk_names[ID_TD_SLCK] = kmemdup(clk_hw_get_name(c), + strlen(clk_hw_get_name(c)) + 1, + GFP_KERNEL); + if (!clk_names[ID_TD_SLCK]) + return -ENOMEM; + + ret = clk_get_by_index(dev, 1, &clk); + if (ret) + return ret; + ret = clk_get_by_id(clk.id, &c); + if (ret) + return ret; + clk_names[ID_MD_SLCK] = kmemdup(clk_hw_get_name(c), + strlen(clk_hw_get_name(c)) + 1, + GFP_KERNEL); + if (!clk_names[ID_MD_SLCK]) + return -ENOMEM; + + ret = clk_get_by_index(dev, 2, &clk); + if (ret) + return ret; + clk_names[ID_MAIN_XTAL] = kmemdup(clk_hw_get_name(&clk), + strlen(clk_hw_get_name(&clk)) + 1, + GFP_KERNEL); + if (!clk_names[ID_MAIN_XTAL]) + return -ENOMEM; + + main_osc_bypass = dev_read_bool(dev, "atmel,main-osc-bypass"); + + /* Register main rc oscillator. */ + clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_RC_OSC), + at91_clk_main_rc(base, clk_names[ID_MAIN_RC_OSC], + NULL)); + + /* Register main oscillator. */ + clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_OSC), + at91_clk_main_osc(base, clk_names[ID_MAIN_OSC], + clk_names[ID_MAIN_XTAL], main_osc_bypass)); + + /* Register mainck. */ + p[0] = clk_names[ID_MAIN_RC_OSC]; + p[1] = clk_names[ID_MAIN_OSC]; + cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_RC_OSC); + cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_OSC); + prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm, 2, + fail); + clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK), + at91_clk_sam9x5_main(base, clk_names[ID_MAINCK], p, 2, + tmpclkmux, PMC_TYPE_CORE)); + + /* Register PLL fracs clocks. */ + for (i = 0; i < ARRAY_SIZE(sama7d65_plls); i++) { + if (sama7d65_plls[i].t != PLL_TYPE_FRAC) + continue; + + clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, sama7d65_plls[i].cid), + sam9x60_clk_register_frac_pll(base, sama7d65_plls[i].n, + sama7d65_plls[i].p, + sama7d65_plls[i].id, + &pll_characteristics, + sama7d65_plls[i].l, + sama7d65_plls[i].c)); + } + + /* Register PLL div clocks. */ + for (i = 0; i < ARRAY_SIZE(sama7d65_plls); i++) { + if (sama7d65_plls[i].t != PLL_TYPE_DIV) + continue; + + clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, sama7d65_plls[i].cid), + sam9x60_clk_register_div_pll(base, sama7d65_plls[i].n, + sama7d65_plls[i].p, + sama7d65_plls[i].id, + &pll_characteristics, + sama7d65_plls[i].l, + sama7d65_plls[i].c)); + } + + /* Register MCK0_PRES clock. */ + p[0] = clk_names[ID_MD_SLCK]; + p[1] = clk_names[ID_MAINCK]; + p[2] = clk_names[ID_PLL_CPU_DIV]; + p[3] = clk_names[ID_PLL_SYS_DIV]; + cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MD_SLCK); + cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK); + cm[2] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_CPU_DIV); + cm[3] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_SYS_DIV); + prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm, 2, + fail); + clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK0_PRES), + at91_clk_register_master_pres(base, clk_names[ID_MCK0_PRES], + p, 4, &mck0_layout, + &mck0_characteristics, + tmpclkmux)); + + clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK0_DIV), + at91_clk_register_master_div(base, clk_names[ID_MCK0_DIV], + clk_names[ID_MCK0_PRES], + &mck0_layout, + &mck0_characteristics)); + + /* Register MCK1-9 clocks. */ + p[0] = clk_names[ID_MD_SLCK]; + p[1] = clk_names[ID_TD_SLCK]; + p[2] = clk_names[ID_MAINCK]; + p[3] = clk_names[ID_MCK0_DIV]; + m[0] = 0; + m[1] = 1; + m[2] = 2; + m[3] = 3; + cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MD_SLCK); + cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_TD_SLCK); + cm[2] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK); + cm[3] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK0_DIV); + for (i = 0; i < ARRAY_SIZE(sama7d65_mckx); i++) { + for (j = 0; j < sama7d65_mckx[i].ep_count; j++) { + p[4 + j] = sama7d65_mckx[i].ep[j]; + m[4 + j] = sama7d65_mckx[i].ep_mux_table[j]; + cm[4 + j] = AT91_TO_CLK_ID(PMC_TYPE_CORE, + sama7d65_mckx[i].ep_clk_mux_table[j]); + } + + prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm, + 4 + sama7d65_mckx[i].ep_count, fail); + prepare_mux_table(muxallocs, muxallocindex, tmpmux, m, + 4 + sama7d65_mckx[i].ep_count, fail); + + clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, sama7d65_mckx[i].cid), + at91_clk_sama7g5_register_master(base, sama7d65_mckx[i].n, p, + 4 + sama7d65_mckx[i].ep_count, + tmpmux, tmpclkmux, + sama7d65_mckx[i].c, + sama7d65_mckx[i].id)); + } + + /* Register programmable clocks. */ + p[0] = clk_names[ID_MD_SLCK]; + p[1] = clk_names[ID_TD_SLCK]; + p[2] = clk_names[ID_MAINCK]; + p[3] = clk_names[ID_MCK0_DIV]; + p[4] = clk_names[ID_PLL_SYS_DIV]; + p[5] = clk_names[ID_PLL_GPU_DIV]; + p[6] = clk_names[ID_PLL_BAUD_DIV]; + p[7] = clk_names[ID_PLL_AUDIO_DIVPMC]; + p[8] = clk_names[ID_PLL_ETH_DIV]; + p[9] = clk_names[ID_PLL_USB_DIV]; + cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MD_SLCK); + cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_TD_SLCK); + cm[2] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK); + cm[3] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK0_DIV); + cm[4] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_SYS_DIV); + cm[5] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_GPU_DIV); + cm[6] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_BAUD_DIV); + cm[7] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_AUDIO_DIVPMC); + cm[8] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_ETH_DIV); + cm[9] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_USB_DIV); + + for (i = 0; i < ARRAY_SIZE(sama7d65_prog); i++) { + prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm, + 10, fail); + + clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, sama7d65_prog[i].cid), + at91_clk_register_programmable(base, sama7d65_prog[i].n, + p, 10, i, + &programmable_layout, + tmpclkmux, + sama7d65_prog_mux_table)); + } + + /* System clocks. */ + for (i = 0; i < ARRAY_SIZE(sama7d65_systemck); i++) { + clk_dm(AT91_TO_CLK_ID(PMC_TYPE_SYSTEM, sama7d65_systemck[i].cid), + at91_clk_register_system(base, sama7d65_systemck[i].n, + sama7d65_systemck[i].p, + sama7d65_systemck[i].id)); + } + + /* Peripheral clocks. */ + for (i = 0; i < ARRAY_SIZE(sama7d65_periphck); i++) { + clk_dm(AT91_TO_CLK_ID(PMC_TYPE_PERIPHERAL, sama7d65_periphck[i].id), + at91_clk_register_sam9x5_peripheral(base, + &sama7d65_pcr_layout, + sama7d65_periphck[i].n, + sama7d65_periphck[i].p, + sama7d65_periphck[i].id, + &sama7d65_periphck[i].r)); + } + + /* Generic clocks. */ + p[0] = clk_names[ID_MD_SLCK]; + p[1] = clk_names[ID_TD_SLCK]; + p[2] = clk_names[ID_MAINCK]; + p[3] = clk_names[ID_MCK1]; + m[0] = 0; + m[1] = 1; + m[2] = 2; + m[3] = 3; + cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MD_SLCK); + cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_TD_SLCK); + cm[2] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK); + cm[3] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK1); + for (i = 0; i < ARRAY_SIZE(sama7d65_gck); i++) { + for (j = 0; j < sama7d65_gck[i].ep_count; j++) { + p[4 + j] = sama7d65_gck[i].ep[j]; + m[4 + j] = sama7d65_gck[i].ep_mux_table[j]; + cm[4 + j] = AT91_TO_CLK_ID(PMC_TYPE_CORE, + sama7d65_gck[i].ep_clk_mux_table[j]); + } + + prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm, + 4 + sama7d65_gck[i].ep_count, fail); + prepare_mux_table(muxallocs, muxallocindex, tmpmux, m, + 4 + sama7d65_gck[i].ep_count, fail); + + clk_dm(AT91_TO_CLK_ID(PMC_TYPE_GCK, sama7d65_gck[i].id), + at91_clk_register_generic(base, &sama7d65_pcr_layout, + sama7d65_gck[i].n, p, + tmpclkmux, tmpmux, + 4 + sama7d65_gck[i].ep_count, + sama7d65_gck[i].id, + &sama7d65_gck[i].r)); + } + + /* Setup clocks. */ + ret = at91_clk_setup(sama7d65_clk_setup, ARRAY_SIZE(sama7d65_clk_setup)); + if (ret) + goto fail; + + return 0; + +fail: + for (i = 0; i < ARRAY_SIZE(muxallocs); i++) + kfree(muxallocs[i]); + + for (i = 0; i < ARRAY_SIZE(clkmuxallocs); i++) + kfree(clkmuxallocs[i]); + + return -ENOMEM; +} + +static const struct udevice_id sama7d65_clk_ids[] = { + { .compatible = "microchip,sama7d65-pmc" }, + { /* Sentinel. */ }, +}; + +U_BOOT_DRIVER(at91_sama7d65_pmc) = { + .name = "at91-sama7d65-pmc", + .id = UCLASS_CLK, + .of_match = sama7d65_clk_ids, + .ops = &at91_clk_ops, + .probe = sama7d65_clk_probe, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/ddr/altera/sdram_n5x.c b/drivers/ddr/altera/sdram_n5x.c index d1fc93b6bdd..17ec6afa82b 100644 --- a/drivers/ddr/altera/sdram_n5x.c +++ b/drivers/ddr/altera/sdram_n5x.c @@ -346,25 +346,25 @@ struct ddr_handoff { phys_addr_t cntlr_base; size_t cntlr_total_length; enum ddr_type cntlr_t; - size_t cntlr_handoff_length; + int cntlr_handoff_length; /* Second controller attributes*/ phys_addr_t cntlr2_handoff_base; phys_addr_t cntlr2_base; size_t cntlr2_total_length; enum ddr_type cntlr2_t; - size_t cntlr2_handoff_length; + int cntlr2_handoff_length; /* PHY attributes */ phys_addr_t phy_handoff_base; phys_addr_t phy_base; size_t phy_total_length; - size_t phy_handoff_length; + int phy_handoff_length; /* PHY engine attributes */ phys_addr_t phy_engine_handoff_base; size_t phy_engine_total_length; - size_t phy_engine_handoff_length; + int phy_engine_handoff_length; /* Calibration attributes */ phys_addr_t train_imem_base; diff --git a/drivers/ddr/marvell/a38x/mv_ddr4_training_calibration.c b/drivers/ddr/marvell/a38x/mv_ddr4_training_calibration.c index 31b6209416b..84156a1e8ad 100644 --- a/drivers/ddr/marvell/a38x/mv_ddr4_training_calibration.c +++ b/drivers/ddr/marvell/a38x/mv_ddr4_training_calibration.c @@ -64,7 +64,7 @@ static u8 center_high_element_get(u8 dir, u8 pbs_element, u16 lambda, u8 pbs_max static int mv_ddr4_centralization(u8 dev_num, u16 (*lambda)[MAX_BUS_NUM][BUS_WIDTH_IN_BITS], u8 (*copt)[MAX_BUS_NUM], u8 (*pbs_result)[MAX_BUS_NUM][BUS_WIDTH_IN_BITS], u8 (*vw_size)[MAX_BUS_NUM], u8 mode, u16 param0, u8 param1); -static int mv_ddr4_dqs_reposition(u8 dir, u16 *lambda, u8 *pbs_result, char delta, u8 *copt, u8 *dqs_pbs); +static int mv_ddr4_dqs_reposition(u8 dir, u16 *lambda, u8 *pbs_result, s8 delta, u8 *copt, u8 *dqs_pbs); static int mv_ddr4_copt_get(u8 dir, u16 *lambda, u8 *vw_l, u8 *vw_h, u8 *pbs_result, u8 *copt); static int mv_ddr4_center_of_mass_calc(u8 dev_num, u8 if_id, u8 subphy_num, u8 mode, u8 *vw_l, u8 *vw_h, u8 *vw_v, u8 vw_num, u8 *v_opt, u8 *t_opt); @@ -659,7 +659,7 @@ static int mv_ddr4_centralization(u8 dev_num, u16 (*lambda)[MAX_BUS_NUM][BUS_WID } /* if_id */ /* restore cs enable value*/ - for (if_id = 0; if_id < MAX_INTERFACE_NUM - 1; if_id++) { + for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, DUAL_DUNIT_CFG_REG, cs_ena_reg_val[if_id], MASK_ALL_BITS); @@ -895,7 +895,7 @@ static int mv_ddr4_copt_get(u8 dir, u16 *lambda, u8 *vw_l, u8 *vw_h, u8 *pbs_res * It provides with a solution for a single subphy (8 bits). * The calling function is responsible for any additional pbs taps for dqs */ -static int mv_ddr4_dqs_reposition(u8 dir, u16 *lambda, u8 *pbs_result, char delta, u8 *copt, u8 *dqs_pbs) +static int mv_ddr4_dqs_reposition(u8 dir, u16 *lambda, u8 *pbs_result, s8 delta, u8 *copt, u8 *dqs_pbs) { u8 dq_idx; u32 pbs_max_val = 0; @@ -952,7 +952,8 @@ static int mv_ddr4_center_of_mass_calc(u8 dev_num, u8 if_id, u8 subphy_num, u8 m int t_opt_temp = 0, v_opt_temp = 0; int vw_avg = 0, v_avg = 0; int s0 = 0, s1 = 0, s2 = 0, slope = 1, r_sq = 0; - u32 d_min = 10000, reg_val = 0; + u32 reg_val = 0; + int d_min = 10000; int status; /* @@ -2189,7 +2190,7 @@ int mv_ddr4_dm_tuning(u32 cs, u16 (*pbs_tap_factor)[MAX_BUS_NUM][BUS_WIDTH_IN_BI for (dq = 0; dq < BUS_WIDTH_IN_BITS; dq++) { idx = dq + subphy * BUS_WIDTH_IN_BITS; reg_val = new_dq_pbs[dq] - dq_pbs_diff; - if (reg_val < 0) { + if (new_dq_pbs[dq] < dq_pbs_diff) { DEBUG_DM_TUNING(DEBUG_LEVEL_ERROR, ("unexpected negative value found\n")); return MV_FAIL; @@ -2267,7 +2268,7 @@ int mv_ddr4_dm_tuning(u32 cs, u16 (*pbs_tap_factor)[MAX_BUS_NUM][BUS_WIDTH_IN_BI idx = dq + subphy * BUS_WIDTH_IN_BITS; pad = dq_map_table[idx]; reg_val = new_dq_pbs[dq] - dq_pbs_diff; - if (reg_val < 0) { + if (new_dq_pbs[dq] < dq_pbs_diff) { DEBUG_DM_TUNING(DEBUG_LEVEL_ERROR, ("unexpected negative value found\n")); return MV_FAIL; diff --git a/drivers/fpga/socfpga_gen5.c b/drivers/fpga/socfpga_gen5.c index 9473f057328..964a5cc8789 100644 --- a/drivers/fpga/socfpga_gen5.c +++ b/drivers/fpga/socfpga_gen5.c @@ -119,27 +119,14 @@ static int fpgamgr_program_poll_cd(void) { const uint32_t mask = FPGAMGRREGS_MON_GPIO_EXT_PORTA_NS_MASK | FPGAMGRREGS_MON_GPIO_EXT_PORTA_CD_MASK; - unsigned long reg, i; + unsigned long reg; - /* (3) wait until full config done */ - for (i = 0; i < FPGA_TIMEOUT_CNT; i++) { - reg = readl(&fpgamgr_regs->gpio_ext_porta); - - /* Config error */ - if (!(reg & mask)) { - printf("FPGA: Configuration error.\n"); - return -3; - } - - /* Config done without error */ - if (reg & mask) - break; - } + reg = readl(&fpgamgr_regs->gpio_ext_porta); - /* Timeout happened, return error */ - if (i == FPGA_TIMEOUT_CNT) { - printf("FPGA: Timeout waiting for program.\n"); - return -4; + /* Config error */ + if (!(reg & mask)) { + printf("FPGA: Configuration error.\n"); + return -3; } /* Disable AXI configuration */ diff --git a/drivers/misc/socfpga_dtreg.c b/drivers/misc/socfpga_dtreg.c index ea5d0bcdf51..dd6809433e3 100644 --- a/drivers/misc/socfpga_dtreg.c +++ b/drivers/misc/socfpga_dtreg.c @@ -76,16 +76,15 @@ static int socfpga_dtreg_probe(struct udevice *dev) return -EINVAL; } + reg = base + offset; + if (mask != 0) { if (mask == 0xffffffff) { - reg = base + offset; writel(val, (uintptr_t)reg); } else { /* Mask the value with the masking bits */ set_mask = val & mask; - reg = base + offset; - /* Clears and sets specific bits in the register */ clrsetbits_le32((uintptr_t)reg, mask, set_mask); } diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index d942fa4e202..d1cb69f85ad 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -138,30 +138,6 @@ config ALTERA_TSE Please find details on the "Triple-Speed Ethernet MegaCore Function Resource Center" of Altera. -config BCM_SF2_ETH - bool "Broadcom SF2 (Starfighter2) Ethernet support" - select PHYLIB - help - This is an abstract framework which provides a generic interface - to MAC and DMA management for multiple Broadcom SoCs such as - Cygnus, NSP and bcm28155_ap platforms. - -config BCM_SF2_ETH_DEFAULT_PORT - int "Broadcom SF2 (Starfighter2) Ethernet default port number" - depends on BCM_SF2_ETH - default 0 - help - Default port number for the Starfighter2 ethernet driver. - -config BCM_SF2_ETH_GMAC - bool "Broadcom SF2 (Starfighter2) GMAC Ethernet support" - depends on BCM_SF2_ETH - help - This flag enables the ethernet support for Broadcom platforms with - GMAC such as Cygnus. This driver is based on the framework provided - by the BCM_SF2_ETH driver. - Say Y to any bcmcygnus based platforms. - config BCM6348_ETH bool "BCM6348 EMAC support" depends on ARCH_BMIPS @@ -197,6 +173,7 @@ config CORTINA_NI_ENET config CALXEDA_XGMAC bool "Calxeda XGMAC support" + depends on ARCH_HIGHBANK help This driver supports the XGMAC in Calxeda Highbank and Midway machines. @@ -246,14 +223,14 @@ config DWC_ETH_QOS config DWC_ETH_QOS_ADI bool "Synopsys DWC Ethernet QOS device support for ADI SC59x-64 parts" - depends on DWC_ETH_QOS + depends on DWC_ETH_QOS && ARCH_SC5XX help The Synopsis Designware Ethernet QoS IP block with the specific configuration used in the ADI ADSP-SC59X 64 bit SoCs config DWC_ETH_QOS_IMX bool "Synopsys DWC Ethernet QOS device support for IMX" - depends on DWC_ETH_QOS + depends on DWC_ETH_QOS && MACH_IMX help The Synopsys Designware Ethernet QOS IP block with the specific configuration used in IMX soc. @@ -267,7 +244,7 @@ config DWC_ETH_QOS_INTEL config DWC_ETH_QOS_ROCKCHIP bool "Synopsys DWC Ethernet QOS device support for Rockchip SoCs" - depends on DWC_ETH_QOS + depends on DWC_ETH_QOS && ARCH_ROCKCHIP select DM_ETH_PHY help The Synopsys Designware Ethernet QOS IP block with specific @@ -275,7 +252,7 @@ config DWC_ETH_QOS_ROCKCHIP config DWC_ETH_QOS_STM32 bool "Synopsys DWC Ethernet QOS device support for STM32" - depends on DWC_ETH_QOS + depends on DWC_ETH_QOS && ARCH_STM32MP select DM_ETH_PHY default y if ARCH_STM32MP help @@ -327,7 +304,7 @@ config E1000_SPI_GENERIC config E1000_SPI bool "Enable SPI bus utility code" - depends on E1000 + depends on E1000 && !E1000_NO_NVM help Utility code for direct access to the SPI bus on Intel 8257x. This does not do anything useful unless you set at least one @@ -343,6 +320,7 @@ config CMD_E1000 config EEPRO100 bool "Intel PRO/100 82557/82559/82559ER Fast Ethernet support" + depends on !64BIT help This driver supports Intel(R) PRO/100 82557/82559/82559ER fast ethernet family of adapters. @@ -406,7 +384,7 @@ config ETH_DESIGNWARE_SOCFPGA config ETH_DESIGNWARE_S700 bool "Actins S700 glue driver for Synopsys Designware Ethernet MAC" - depends on ETH_DESIGNWARE + depends on ETH_DESIGNWARE && ARCH_OWL help This provides glue layer to use Synopsys Designware Ethernet MAC present on Actions S700 SoC. @@ -448,7 +426,7 @@ config FEC_MXC config FMAN_ENET bool "Freescale FMan ethernet support" - depends on ARM || PPC + depends on FSL_LSCH2 || PPC select SYS_FMAN_V3 if ARCH_B4420 || ARCH_B4860 || ARCH_LS1043A || \ ARCH_LS1046A || ARCH_T1024 || ARCH_T1040 || ARCH_T1042 || \ ARCH_T2080 || ARCH_T4240 @@ -520,6 +498,7 @@ config SYS_DISCOVER_PHY config MCFFEC bool "ColdFire Ethernet Support" + depends on M68K select PHYLIB select SYS_DISCOVER_PHY help @@ -583,6 +562,7 @@ config MVPP2 config MACB bool "Cadence MACB/GEM Ethernet Interface" + depends on ARM || RISCV select PHYLIB help The Cadence MACB ethernet interface is found on many Atmel @@ -619,6 +599,7 @@ config MT7628_ETH config NET_NPCM750 bool "Nuvoton NPCM750 Ethernet MAC" + depends on ARCH_NPCM help support NPCM750 EMAC @@ -693,6 +674,7 @@ source "drivers/net/qe/Kconfig" config RTL8139 bool "Realtek 8139 series Ethernet controller driver" + depends on !64BIT help This driver supports Realtek 8139 series fast ethernet family of PCI chipsets/adapters. @@ -746,6 +728,7 @@ config SUN7I_GMAC_FORCE_TXERR config SUN4I_EMAC bool "Allwinner Sun4i Ethernet MAC support" + depends on ARCH_SUNXI select PHYLIB help This driver supports the Allwinner based SUN4I Ethernet MAC. @@ -761,6 +744,7 @@ config SUN8I_EMAC config SH_ETHER bool "Renesas SH Ethernet MAC" + depends on ARCH_RENESAS select PHYLIB select PHY_ETHERNET_ID help @@ -770,6 +754,7 @@ source "drivers/net/ti/Kconfig" config TULIP bool "DEC Tulip DC2114x Ethernet support" + depends on !64BIT help This driver supports DEC DC2114x Fast ethernet chips. @@ -823,6 +808,7 @@ config XILINX_AXIMRMAC config VSC7385_ENET bool "Vitesse 7385 Switch Firmware Upload driver" + depends on !COMPILE_TEST && PPC config XILINX_EMACLITE select PHYLIB @@ -834,6 +820,7 @@ config XILINX_EMACLITE config ZYNQ_GEM select PHYLIB bool "Xilinx Ethernet GEM" + depends on ARCH_VERSAL || ARCH_VERSAL_NET || ARCH_VERSAL2 || ARCH_ZYNQ || ARCH_ZYNQMP help This MAC is present in Xilinx Zynq and ZynqMP SoCs. @@ -847,7 +834,7 @@ config PIC32_ETH config GMAC_ROCKCHIP bool "Rockchip Synopsys Designware Ethernet MAC" - depends on ETH_DESIGNWARE + depends on ETH_DESIGNWARE && ARCH_ROCKCHIP help This driver provides Rockchip SoCs network support based on the Synopsys Designware driver. @@ -974,6 +961,7 @@ config SYS_FSL_QMAN_V3 config TSEC_ENET select PHYLIB bool "Enable Three-Speed Ethernet Controller" + depends on ARCH_LS1021A || PPC help This driver implements support for the (Enhanced) Three-Speed Ethernet Controller found on Freescale SoCs. diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 79cc8b422b0..f8f9a71f815 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -11,8 +11,6 @@ obj-$(CONFIG_ASPEED_MDIO) += aspeed_mdio.o obj-$(CONFIG_BCM6348_ETH) += bcm6348-eth.o obj-$(CONFIG_BCM6368_ETH) += bcm6368-eth.o obj-$(CONFIG_BCMGENET) += bcmgenet.o -obj-$(CONFIG_BCM_SF2_ETH) += bcm-sf2-eth.o -obj-$(CONFIG_BCM_SF2_ETH_GMAC) += bcm-sf2-eth-gmac.o obj-$(CONFIG_BNXT_ETH) += bnxt/ obj-$(CONFIG_CALXEDA_XGMAC) += calxedaxgmac.o obj-$(CONFIG_CORTINA_NI_ENET) += cortina_ni.o diff --git a/drivers/net/bcm-sf2-eth-gmac.c b/drivers/net/bcm-sf2-eth-gmac.c deleted file mode 100644 index ba244b4a26e..00000000000 --- a/drivers/net/bcm-sf2-eth-gmac.c +++ /dev/null @@ -1,976 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright 2014-2017 Broadcom. - */ - -#ifdef BCM_GMAC_DEBUG -#ifndef DEBUG -#define DEBUG -#include <linux/printk.h> -#endif -#endif - -#include <config.h> -#include <cpu_func.h> -#include <log.h> -#include <malloc.h> -#include <net.h> -#include <asm/cache.h> -#include <asm/io.h> -#include <phy.h> -#include <linux/delay.h> -#include <linux/bitops.h> - -#include "bcm-sf2-eth.h" -#include "bcm-sf2-eth-gmac.h" - -#define SPINWAIT(exp, us) { \ - uint countdown = (us) + 9; \ - while ((exp) && (countdown >= 10)) {\ - udelay(10); \ - countdown -= 10; \ - } \ -} - -#define RX_BUF_SIZE_ALIGNED ALIGN(RX_BUF_SIZE, ARCH_DMA_MINALIGN) -#define TX_BUF_SIZE_ALIGNED ALIGN(TX_BUF_SIZE, ARCH_DMA_MINALIGN) -#define DESCP_SIZE_ALIGNED ALIGN(sizeof(dma64dd_t), ARCH_DMA_MINALIGN) - -static int gmac_disable_dma(struct eth_dma *dma, int dir); -static int gmac_enable_dma(struct eth_dma *dma, int dir); - -/* DMA Descriptor */ -typedef struct { - /* misc control bits */ - uint32_t ctrl1; - /* buffer count and address extension */ - uint32_t ctrl2; - /* memory address of the date buffer, bits 31:0 */ - uint32_t addrlow; - /* memory address of the date buffer, bits 63:32 */ - uint32_t addrhigh; -} dma64dd_t; - -uint32_t g_dmactrlflags; - -static uint32_t dma_ctrlflags(uint32_t mask, uint32_t flags) -{ - debug("%s enter\n", __func__); - - g_dmactrlflags &= ~mask; - g_dmactrlflags |= flags; - - /* If trying to enable parity, check if parity is actually supported */ - if (g_dmactrlflags & DMA_CTRL_PEN) { - uint32_t control; - - control = readl(GMAC0_DMA_TX_CTRL_ADDR); - writel(control | D64_XC_PD, GMAC0_DMA_TX_CTRL_ADDR); - if (readl(GMAC0_DMA_TX_CTRL_ADDR) & D64_XC_PD) { - /* - * We *can* disable it, therefore it is supported; - * restore control register - */ - writel(control, GMAC0_DMA_TX_CTRL_ADDR); - } else { - /* Not supported, don't allow it to be enabled */ - g_dmactrlflags &= ~DMA_CTRL_PEN; - } - } - - return g_dmactrlflags; -} - -static inline void reg32_clear_bits(uint32_t reg, uint32_t value) -{ - uint32_t v = readl(reg); - v &= ~(value); - writel(v, reg); -} - -static inline void reg32_set_bits(uint32_t reg, uint32_t value) -{ - uint32_t v = readl(reg); - v |= value; - writel(v, reg); -} - -#ifdef BCM_GMAC_DEBUG -static void dma_tx_dump(struct eth_dma *dma) -{ - dma64dd_t *descp = NULL; - uint8_t *bufp; - int i; - - printf("TX DMA Register:\n"); - printf("control:0x%x; ptr:0x%x; addrl:0x%x; addrh:0x%x; stat0:0x%x, stat1:0x%x\n", - readl(GMAC0_DMA_TX_CTRL_ADDR), - readl(GMAC0_DMA_TX_PTR_ADDR), - readl(GMAC0_DMA_TX_ADDR_LOW_ADDR), - readl(GMAC0_DMA_TX_ADDR_HIGH_ADDR), - readl(GMAC0_DMA_TX_STATUS0_ADDR), - readl(GMAC0_DMA_TX_STATUS1_ADDR)); - - printf("TX Descriptors:\n"); - for (i = 0; i < TX_BUF_NUM; i++) { - descp = (dma64dd_t *)(dma->tx_desc_aligned) + i; - printf("ctrl1:0x%08x; ctrl2:0x%08x; addr:0x%x 0x%08x\n", - descp->ctrl1, descp->ctrl2, - descp->addrhigh, descp->addrlow); - } - - printf("TX Buffers:\n"); - /* Initialize TX DMA descriptor table */ - for (i = 0; i < TX_BUF_NUM; i++) { - bufp = (uint8_t *)(dma->tx_buf + i * TX_BUF_SIZE_ALIGNED); - printf("buf%d:0x%x; ", i, (uint32_t)bufp); - } - printf("\n"); -} - -static void dma_rx_dump(struct eth_dma *dma) -{ - dma64dd_t *descp = NULL; - uint8_t *bufp; - int i; - - printf("RX DMA Register:\n"); - printf("control:0x%x; ptr:0x%x; addrl:0x%x; addrh:0x%x; stat0:0x%x, stat1:0x%x\n", - readl(GMAC0_DMA_RX_CTRL_ADDR), - readl(GMAC0_DMA_RX_PTR_ADDR), - readl(GMAC0_DMA_RX_ADDR_LOW_ADDR), - readl(GMAC0_DMA_RX_ADDR_HIGH_ADDR), - readl(GMAC0_DMA_RX_STATUS0_ADDR), - readl(GMAC0_DMA_RX_STATUS1_ADDR)); - - printf("RX Descriptors:\n"); - for (i = 0; i < RX_BUF_NUM; i++) { - descp = (dma64dd_t *)(dma->rx_desc_aligned) + i; - printf("ctrl1:0x%08x; ctrl2:0x%08x; addr:0x%x 0x%08x\n", - descp->ctrl1, descp->ctrl2, - descp->addrhigh, descp->addrlow); - } - - printf("RX Buffers:\n"); - for (i = 0; i < RX_BUF_NUM; i++) { - bufp = dma->rx_buf + i * RX_BUF_SIZE_ALIGNED; - printf("buf%d:0x%x; ", i, (uint32_t)bufp); - } - printf("\n"); -} -#endif - -static int dma_tx_init(struct eth_dma *dma) -{ - dma64dd_t *descp = NULL; - uint8_t *bufp; - int i; - uint32_t ctrl; - - debug("%s enter\n", __func__); - - /* clear descriptor memory */ - memset((void *)(dma->tx_desc_aligned), 0, - TX_BUF_NUM * DESCP_SIZE_ALIGNED); - memset(dma->tx_buf, 0, TX_BUF_NUM * TX_BUF_SIZE_ALIGNED); - - /* Initialize TX DMA descriptor table */ - for (i = 0; i < TX_BUF_NUM; i++) { - descp = (dma64dd_t *)(dma->tx_desc_aligned) + i; - bufp = dma->tx_buf + i * TX_BUF_SIZE_ALIGNED; - /* clear buffer memory */ - memset((void *)bufp, 0, TX_BUF_SIZE_ALIGNED); - - ctrl = 0; - /* if last descr set endOfTable */ - if (i == (TX_BUF_NUM-1)) - ctrl = D64_CTRL1_EOT; - descp->ctrl1 = ctrl; - descp->ctrl2 = 0; - descp->addrlow = (uint32_t)bufp; - descp->addrhigh = 0; - } - - /* flush descriptor and buffer */ - descp = dma->tx_desc_aligned; - bufp = dma->tx_buf; - flush_dcache_range((unsigned long)descp, - (unsigned long)descp + - DESCP_SIZE_ALIGNED * TX_BUF_NUM); - flush_dcache_range((unsigned long)bufp, - (unsigned long)bufp + - TX_BUF_SIZE_ALIGNED * TX_BUF_NUM); - - /* initialize the DMA channel */ - writel((uint32_t)(dma->tx_desc_aligned), GMAC0_DMA_TX_ADDR_LOW_ADDR); - writel(0, GMAC0_DMA_TX_ADDR_HIGH_ADDR); - - /* now update the dma last descriptor */ - writel(((uint32_t)(dma->tx_desc_aligned)) & D64_XP_LD_MASK, - GMAC0_DMA_TX_PTR_ADDR); - - return 0; -} - -static int dma_rx_init(struct eth_dma *dma) -{ - uint32_t last_desc; - dma64dd_t *descp = NULL; - uint8_t *bufp; - uint32_t ctrl; - int i; - - debug("%s enter\n", __func__); - - /* clear descriptor memory */ - memset((void *)(dma->rx_desc_aligned), 0, - RX_BUF_NUM * DESCP_SIZE_ALIGNED); - /* clear buffer memory */ - memset(dma->rx_buf, 0, RX_BUF_NUM * RX_BUF_SIZE_ALIGNED); - - /* Initialize RX DMA descriptor table */ - for (i = 0; i < RX_BUF_NUM; i++) { - descp = (dma64dd_t *)(dma->rx_desc_aligned) + i; - bufp = dma->rx_buf + i * RX_BUF_SIZE_ALIGNED; - ctrl = 0; - /* if last descr set endOfTable */ - if (i == (RX_BUF_NUM - 1)) - ctrl = D64_CTRL1_EOT; - descp->ctrl1 = ctrl; - descp->ctrl2 = RX_BUF_SIZE_ALIGNED; - descp->addrlow = (uint32_t)bufp; - descp->addrhigh = 0; - - last_desc = ((uint32_t)(descp) & D64_XP_LD_MASK) - + sizeof(dma64dd_t); - } - - descp = dma->rx_desc_aligned; - bufp = dma->rx_buf; - /* flush descriptor and buffer */ - flush_dcache_range((unsigned long)descp, - (unsigned long)descp + - DESCP_SIZE_ALIGNED * RX_BUF_NUM); - flush_dcache_range((unsigned long)(bufp), - (unsigned long)bufp + - RX_BUF_SIZE_ALIGNED * RX_BUF_NUM); - - /* initailize the DMA channel */ - writel((uint32_t)descp, GMAC0_DMA_RX_ADDR_LOW_ADDR); - writel(0, GMAC0_DMA_RX_ADDR_HIGH_ADDR); - - /* now update the dma last descriptor */ - writel(last_desc, GMAC0_DMA_RX_PTR_ADDR); - - return 0; -} - -static int dma_init(struct eth_dma *dma) -{ - debug(" %s enter\n", __func__); - - /* - * Default flags: For backwards compatibility both - * Rx Overflow Continue and Parity are DISABLED. - */ - dma_ctrlflags(DMA_CTRL_ROC | DMA_CTRL_PEN, 0); - - debug("rx burst len 0x%x\n", - (readl(GMAC0_DMA_RX_CTRL_ADDR) & D64_RC_BL_MASK) - >> D64_RC_BL_SHIFT); - debug("tx burst len 0x%x\n", - (readl(GMAC0_DMA_TX_CTRL_ADDR) & D64_XC_BL_MASK) - >> D64_XC_BL_SHIFT); - - dma_tx_init(dma); - dma_rx_init(dma); - - /* From end of chip_init() */ - /* enable the overflow continue feature and disable parity */ - dma_ctrlflags(DMA_CTRL_ROC | DMA_CTRL_PEN /* mask */, - DMA_CTRL_ROC /* value */); - - return 0; -} - -static int dma_deinit(struct eth_dma *dma) -{ - debug(" %s enter\n", __func__); - - gmac_disable_dma(dma, MAC_DMA_RX); - gmac_disable_dma(dma, MAC_DMA_TX); - - free(dma->tx_buf); - dma->tx_buf = NULL; - free(dma->tx_desc_aligned); - dma->tx_desc_aligned = NULL; - - free(dma->rx_buf); - dma->rx_buf = NULL; - free(dma->rx_desc_aligned); - dma->rx_desc_aligned = NULL; - - return 0; -} - -int gmac_tx_packet(struct eth_dma *dma, void *packet, int length) -{ - uint8_t *bufp = dma->tx_buf + dma->cur_tx_index * TX_BUF_SIZE_ALIGNED; - - /* kick off the dma */ - size_t len = length; - int txout = dma->cur_tx_index; - uint32_t flags; - dma64dd_t *descp = NULL; - uint32_t ctrl; - uint32_t last_desc = (((uint32_t)dma->tx_desc_aligned) + - sizeof(dma64dd_t)) & D64_XP_LD_MASK; - size_t buflen; - - debug("%s enter\n", __func__); - - /* load the buffer */ - memcpy(bufp, packet, len); - - /* Add 4 bytes for Ethernet FCS/CRC */ - buflen = len + 4; - - ctrl = (buflen & D64_CTRL2_BC_MASK); - - /* the transmit will only be one frame or set SOF, EOF */ - /* also set int on completion */ - flags = D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF; - - /* txout points to the descriptor to uset */ - /* if last descriptor then set EOT */ - if (txout == (TX_BUF_NUM - 1)) { - flags |= D64_CTRL1_EOT; - last_desc = ((uint32_t)(dma->tx_desc_aligned)) & D64_XP_LD_MASK; - } - - /* write the descriptor */ - descp = ((dma64dd_t *)(dma->tx_desc_aligned)) + txout; - descp->addrlow = (uint32_t)bufp; - descp->addrhigh = 0; - descp->ctrl1 = flags; - descp->ctrl2 = ctrl; - - /* flush descriptor and buffer */ - flush_dcache_range((unsigned long)dma->tx_desc_aligned, - (unsigned long)dma->tx_desc_aligned + - DESCP_SIZE_ALIGNED * TX_BUF_NUM); - flush_dcache_range((unsigned long)bufp, - (unsigned long)bufp + TX_BUF_SIZE_ALIGNED); - - /* now update the dma last descriptor */ - writel(last_desc, GMAC0_DMA_TX_PTR_ADDR); - - /* tx dma should be enabled so packet should go out */ - - /* update txout */ - dma->cur_tx_index = (txout + 1) & (TX_BUF_NUM - 1); - - return 0; -} - -bool gmac_check_tx_done(struct eth_dma *dma) -{ - /* wait for tx to complete */ - uint32_t intstatus; - bool xfrdone = false; - - debug("%s enter\n", __func__); - - intstatus = readl(GMAC0_INT_STATUS_ADDR); - - debug("int(0x%x)\n", intstatus); - if (intstatus & (I_XI0 | I_XI1 | I_XI2 | I_XI3)) { - xfrdone = true; - /* clear the int bits */ - intstatus &= ~(I_XI0 | I_XI1 | I_XI2 | I_XI3); - writel(intstatus, GMAC0_INT_STATUS_ADDR); - } else { - debug("Tx int(0x%x)\n", intstatus); - } - - return xfrdone; -} - -int gmac_check_rx_done(struct eth_dma *dma, uint8_t *buf) -{ - void *bufp, *datap; - size_t rcvlen = 0, buflen = 0; - uint32_t stat0 = 0, stat1 = 0; - uint32_t control, offset; - uint8_t statbuf[HWRXOFF*2]; - - int index, curr, active; - dma64dd_t *descp = NULL; - - /* udelay(50); */ - - /* - * this api will check if a packet has been received. - * If so it will return the address of the buffer and current - * descriptor index will be incremented to the - * next descriptor. Once done with the frame the buffer should be - * added back onto the descriptor and the lastdscr should be updated - * to this descriptor. - */ - index = dma->cur_rx_index; - offset = (uint32_t)(dma->rx_desc_aligned); - stat0 = readl(GMAC0_DMA_RX_STATUS0_ADDR) & D64_RS0_CD_MASK; - stat1 = readl(GMAC0_DMA_RX_STATUS1_ADDR) & D64_RS0_CD_MASK; - curr = ((stat0 - offset) & D64_RS0_CD_MASK) / sizeof(dma64dd_t); - active = ((stat1 - offset) & D64_RS0_CD_MASK) / sizeof(dma64dd_t); - - /* check if any frame */ - if (index == curr) - return -1; - - debug("received packet\n"); - debug("expect(0x%x) curr(0x%x) active(0x%x)\n", index, curr, active); - /* remove warning */ - if (index == active) - ; - - /* get the packet pointer that corresponds to the rx descriptor */ - bufp = dma->rx_buf + index * RX_BUF_SIZE_ALIGNED; - - descp = (dma64dd_t *)(dma->rx_desc_aligned) + index; - /* flush descriptor and buffer */ - flush_dcache_range((unsigned long)dma->rx_desc_aligned, - (unsigned long)dma->rx_desc_aligned + - DESCP_SIZE_ALIGNED * RX_BUF_NUM); - flush_dcache_range((unsigned long)bufp, - (unsigned long)bufp + RX_BUF_SIZE_ALIGNED); - - buflen = (descp->ctrl2 & D64_CTRL2_BC_MASK); - - stat0 = readl(GMAC0_DMA_RX_STATUS0_ADDR); - stat1 = readl(GMAC0_DMA_RX_STATUS1_ADDR); - - debug("bufp(0x%x) index(0x%x) buflen(0x%x) stat0(0x%x) stat1(0x%x)\n", - (uint32_t)bufp, index, buflen, stat0, stat1); - - dma->cur_rx_index = (index + 1) & (RX_BUF_NUM - 1); - - /* get buffer offset */ - control = readl(GMAC0_DMA_RX_CTRL_ADDR); - offset = (control & D64_RC_RO_MASK) >> D64_RC_RO_SHIFT; - rcvlen = *(uint16_t *)bufp; - - debug("Received %d bytes\n", rcvlen); - /* copy status into temp buf then copy data from rx buffer */ - memcpy(statbuf, bufp, offset); - datap = (void *)((uint32_t)bufp + offset); - memcpy(buf, datap, rcvlen); - - /* update descriptor that is being added back on ring */ - descp->ctrl2 = RX_BUF_SIZE_ALIGNED; - descp->addrlow = (uint32_t)bufp; - descp->addrhigh = 0; - /* flush descriptor */ - flush_dcache_range((unsigned long)dma->rx_desc_aligned, - (unsigned long)dma->rx_desc_aligned + - DESCP_SIZE_ALIGNED * RX_BUF_NUM); - - /* set the lastdscr for the rx ring */ - writel(((uint32_t)descp) & D64_XP_LD_MASK, GMAC0_DMA_RX_PTR_ADDR); - - return (int)rcvlen; -} - -static int gmac_disable_dma(struct eth_dma *dma, int dir) -{ - int status; - - debug("%s enter\n", __func__); - - if (dir == MAC_DMA_TX) { - /* address PR8249/PR7577 issue */ - /* suspend tx DMA first */ - writel(D64_XC_SE, GMAC0_DMA_TX_CTRL_ADDR); - SPINWAIT(((status = (readl(GMAC0_DMA_TX_STATUS0_ADDR) & - D64_XS0_XS_MASK)) != - D64_XS0_XS_DISABLED) && - (status != D64_XS0_XS_IDLE) && - (status != D64_XS0_XS_STOPPED), 10000); - - /* - * PR2414 WAR: DMA engines are not disabled until - * transfer finishes - */ - writel(0, GMAC0_DMA_TX_CTRL_ADDR); - SPINWAIT(((status = (readl(GMAC0_DMA_TX_STATUS0_ADDR) & - D64_XS0_XS_MASK)) != - D64_XS0_XS_DISABLED), 10000); - - /* wait for the last transaction to complete */ - udelay(2); - - status = (status == D64_XS0_XS_DISABLED); - } else { - /* - * PR2414 WAR: DMA engines are not disabled until - * transfer finishes - */ - writel(0, GMAC0_DMA_RX_CTRL_ADDR); - SPINWAIT(((status = (readl(GMAC0_DMA_RX_STATUS0_ADDR) & - D64_RS0_RS_MASK)) != - D64_RS0_RS_DISABLED), 10000); - - status = (status == D64_RS0_RS_DISABLED); - } - - return status; -} - -static int gmac_enable_dma(struct eth_dma *dma, int dir) -{ - uint32_t control; - - debug("%s enter\n", __func__); - - if (dir == MAC_DMA_TX) { - dma->cur_tx_index = 0; - - /* - * These bits 20:18 (burstLen) of control register can be - * written but will take effect only if these bits are - * valid. So this will not affect previous versions - * of the DMA. They will continue to have those bits set to 0. - */ - control = readl(GMAC0_DMA_TX_CTRL_ADDR); - - control |= D64_XC_XE; - if ((g_dmactrlflags & DMA_CTRL_PEN) == 0) - control |= D64_XC_PD; - - writel(control, GMAC0_DMA_TX_CTRL_ADDR); - - /* initailize the DMA channel */ - writel((uint32_t)(dma->tx_desc_aligned), - GMAC0_DMA_TX_ADDR_LOW_ADDR); - writel(0, GMAC0_DMA_TX_ADDR_HIGH_ADDR); - } else { - dma->cur_rx_index = 0; - - control = (readl(GMAC0_DMA_RX_CTRL_ADDR) & - D64_RC_AE) | D64_RC_RE; - - if ((g_dmactrlflags & DMA_CTRL_PEN) == 0) - control |= D64_RC_PD; - - if (g_dmactrlflags & DMA_CTRL_ROC) - control |= D64_RC_OC; - - /* - * These bits 20:18 (burstLen) of control register can be - * written but will take effect only if these bits are - * valid. So this will not affect previous versions - * of the DMA. They will continue to have those bits set to 0. - */ - control &= ~D64_RC_BL_MASK; - /* Keep default Rx burstlen */ - control |= readl(GMAC0_DMA_RX_CTRL_ADDR) & D64_RC_BL_MASK; - control |= HWRXOFF << D64_RC_RO_SHIFT; - - writel(control, GMAC0_DMA_RX_CTRL_ADDR); - - /* - * the rx descriptor ring should have - * the addresses set properly; - * set the lastdscr for the rx ring - */ - writel(((uint32_t)(dma->rx_desc_aligned) + - (RX_BUF_NUM - 1) * RX_BUF_SIZE_ALIGNED) & - D64_XP_LD_MASK, GMAC0_DMA_RX_PTR_ADDR); - } - - return 0; -} - -bool gmac_mii_busywait(unsigned int timeout) -{ - uint32_t tmp = 0; - - while (timeout > 10) { - tmp = readl(GMAC_MII_CTRL_ADDR); - if (tmp & (1 << GMAC_MII_BUSY_SHIFT)) { - udelay(10); - timeout -= 10; - } else { - break; - } - } - return tmp & (1 << GMAC_MII_BUSY_SHIFT); -} - -int gmac_miiphy_read(struct mii_dev *bus, int phyaddr, int devad, int reg) -{ - uint32_t tmp = 0; - u16 value = 0; - - /* Busy wait timeout is 1ms */ - if (gmac_mii_busywait(1000)) { - pr_err("%s: Prepare MII read: MII/MDIO busy\n", __func__); - return -1; - } - - /* Read operation */ - tmp = GMAC_MII_DATA_READ_CMD; - tmp |= (phyaddr << GMAC_MII_PHY_ADDR_SHIFT) | - (reg << GMAC_MII_PHY_REG_SHIFT); - debug("MII read cmd 0x%x, phy 0x%x, reg 0x%x\n", tmp, phyaddr, reg); - writel(tmp, GMAC_MII_DATA_ADDR); - - if (gmac_mii_busywait(1000)) { - pr_err("%s: MII read failure: MII/MDIO busy\n", __func__); - return -1; - } - - value = readl(GMAC_MII_DATA_ADDR) & 0xffff; - debug("MII read data 0x%x\n", value); - return value; -} - -int gmac_miiphy_write(struct mii_dev *bus, int phyaddr, int devad, int reg, - u16 value) -{ - uint32_t tmp = 0; - - /* Busy wait timeout is 1ms */ - if (gmac_mii_busywait(1000)) { - pr_err("%s: Prepare MII write: MII/MDIO busy\n", __func__); - return -1; - } - - /* Write operation */ - tmp = GMAC_MII_DATA_WRITE_CMD | (value & 0xffff); - tmp |= ((phyaddr << GMAC_MII_PHY_ADDR_SHIFT) | - (reg << GMAC_MII_PHY_REG_SHIFT)); - debug("MII write cmd 0x%x, phy 0x%x, reg 0x%x, data 0x%x\n", - tmp, phyaddr, reg, value); - writel(tmp, GMAC_MII_DATA_ADDR); - - if (gmac_mii_busywait(1000)) { - pr_err("%s: MII write failure: MII/MDIO busy\n", __func__); - return -1; - } - - return 0; -} - -void gmac_init_reset(void) -{ - debug("%s enter\n", __func__); - - /* set command config reg CC_SR */ - reg32_set_bits(UNIMAC0_CMD_CFG_ADDR, CC_SR); - udelay(GMAC_RESET_DELAY); -} - -void gmac_clear_reset(void) -{ - debug("%s enter\n", __func__); - - /* clear command config reg CC_SR */ - reg32_clear_bits(UNIMAC0_CMD_CFG_ADDR, CC_SR); - udelay(GMAC_RESET_DELAY); -} - -static void gmac_enable_local(bool en) -{ - uint32_t cmdcfg; - - debug("%s enter\n", __func__); - - /* read command config reg */ - cmdcfg = readl(UNIMAC0_CMD_CFG_ADDR); - - /* put mac in reset */ - gmac_init_reset(); - - cmdcfg |= CC_SR; - - /* first deassert rx_ena and tx_ena while in reset */ - cmdcfg &= ~(CC_RE | CC_TE); - /* write command config reg */ - writel(cmdcfg, UNIMAC0_CMD_CFG_ADDR); - - /* bring mac out of reset */ - gmac_clear_reset(); - - /* if not enable exit now */ - if (!en) - return; - - /* enable the mac transmit and receive paths now */ - udelay(2); - cmdcfg &= ~CC_SR; - cmdcfg |= (CC_RE | CC_TE); - - /* assert rx_ena and tx_ena when out of reset to enable the mac */ - writel(cmdcfg, UNIMAC0_CMD_CFG_ADDR); - - return; -} - -int gmac_enable(void) -{ - gmac_enable_local(1); - - /* clear interrupts */ - writel(I_INTMASK, GMAC0_INT_STATUS_ADDR); - return 0; -} - -int gmac_disable(void) -{ - gmac_enable_local(0); - return 0; -} - -int gmac_set_speed(int speed, int duplex) -{ - uint32_t cmdcfg; - uint32_t hd_ena; - uint32_t speed_cfg; - - hd_ena = duplex ? 0 : CC_HD; - if (speed == 1000) { - speed_cfg = 2; - } else if (speed == 100) { - speed_cfg = 1; - } else if (speed == 10) { - speed_cfg = 0; - } else { - pr_err("%s: Invalid GMAC speed(%d)!\n", __func__, speed); - return -1; - } - - cmdcfg = readl(UNIMAC0_CMD_CFG_ADDR); - cmdcfg &= ~(CC_ES_MASK | CC_HD); - cmdcfg |= ((speed_cfg << CC_ES_SHIFT) | hd_ena); - - printf("Change GMAC speed to %dMB\n", speed); - debug("GMAC speed cfg 0x%x\n", cmdcfg); - writel(cmdcfg, UNIMAC0_CMD_CFG_ADDR); - - return 0; -} - -int gmac_set_mac_addr(unsigned char *mac) -{ - /* set our local address */ - debug("GMAC: %02x:%02x:%02x:%02x:%02x:%02x\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - writel(htonl(*(uint32_t *)mac), UNIMAC0_MAC_MSB_ADDR); - writew(htons(*(uint32_t *)&mac[4]), UNIMAC0_MAC_LSB_ADDR); - - return 0; -} - -int gmac_mac_init(struct eth_device *dev) -{ - struct eth_info *eth = (struct eth_info *)(dev->priv); - struct eth_dma *dma = &(eth->dma); - - uint32_t tmp; - uint32_t cmdcfg; - int chipid; - - debug("%s enter\n", __func__); - - /* Always use GMAC0 */ - printf("Using GMAC%d\n", 0); - - /* Reset AMAC0 core */ - writel(0, AMAC0_IDM_RESET_ADDR); - tmp = readl(AMAC0_IO_CTRL_DIRECT_ADDR); - /* Set clock */ - tmp &= ~(1 << AMAC0_IO_CTRL_CLK_250_SEL_SHIFT); - tmp |= (1 << AMAC0_IO_CTRL_GMII_MODE_SHIFT); - /* Set Tx clock */ - tmp &= ~(1 << AMAC0_IO_CTRL_DEST_SYNC_MODE_EN_SHIFT); - writel(tmp, AMAC0_IO_CTRL_DIRECT_ADDR); - - /* reset gmac */ - /* - * As AMAC is just reset, NO need? - * set eth_data into loopback mode to ensure no rx traffic - * gmac_loopback(eth_data, TRUE); - * ET_TRACE(("%s gmac loopback\n", __func__)); - * udelay(1); - */ - - cmdcfg = readl(UNIMAC0_CMD_CFG_ADDR); - cmdcfg &= ~(CC_TE | CC_RE | CC_RPI | CC_TAI | CC_HD | CC_ML | - CC_CFE | CC_RL | CC_RED | CC_PE | CC_TPI | - CC_PAD_EN | CC_PF); - cmdcfg |= (CC_PROM | CC_NLC | CC_CFE); - /* put mac in reset */ - gmac_init_reset(); - writel(cmdcfg, UNIMAC0_CMD_CFG_ADDR); - gmac_clear_reset(); - - /* enable clear MIB on read */ - reg32_set_bits(GMAC0_DEV_CTRL_ADDR, DC_MROR); - /* PHY: set smi_master to drive mdc_clk */ - reg32_set_bits(GMAC0_PHY_CTRL_ADDR, PC_MTE); - - /* clear persistent sw intstatus */ - writel(0, GMAC0_INT_STATUS_ADDR); - - if (dma_init(dma) < 0) { - pr_err("%s: GMAC dma_init failed\n", __func__); - goto err_exit; - } - - chipid = CHIPID; - printf("%s: Chip ID: 0x%x\n", __func__, chipid); - - /* set switch bypass mode */ - tmp = readl(SWITCH_GLOBAL_CONFIG_ADDR); - tmp |= (1 << CDRU_SWITCH_BYPASS_SWITCH_SHIFT); - - /* Switch mode */ - /* tmp &= ~(1 << CDRU_SWITCH_BYPASS_SWITCH_SHIFT); */ - - writel(tmp, SWITCH_GLOBAL_CONFIG_ADDR); - - tmp = readl(CRMU_CHIP_IO_PAD_CONTROL_ADDR); - tmp &= ~(1 << CDRU_IOMUX_FORCE_PAD_IN_SHIFT); - writel(tmp, CRMU_CHIP_IO_PAD_CONTROL_ADDR); - - /* Set MDIO to internal GPHY */ - tmp = readl(GMAC_MII_CTRL_ADDR); - /* Select internal MDC/MDIO bus*/ - tmp &= ~(1 << GMAC_MII_CTRL_BYP_SHIFT); - /* select MDC/MDIO connecting to on-chip internal PHYs */ - tmp &= ~(1 << GMAC_MII_CTRL_EXT_SHIFT); - /* - * give bit[6:0](MDCDIV) with required divisor to set - * the MDC clock frequency, 66MHZ/0x1A=2.5MHZ - */ - tmp |= 0x1A; - - writel(tmp, GMAC_MII_CTRL_ADDR); - - if (gmac_mii_busywait(1000)) { - pr_err("%s: Configure MDIO: MII/MDIO busy\n", __func__); - goto err_exit; - } - - /* Configure GMAC0 */ - /* enable one rx interrupt per received frame */ - writel(1 << GMAC0_IRL_FRAMECOUNT_SHIFT, GMAC0_INTR_RECV_LAZY_ADDR); - - /* read command config reg */ - cmdcfg = readl(UNIMAC0_CMD_CFG_ADDR); - /* enable 802.3x tx flow control (honor received PAUSE frames) */ - cmdcfg &= ~CC_RPI; - /* enable promiscuous mode */ - cmdcfg |= CC_PROM; - /* Disable loopback mode */ - cmdcfg &= ~CC_ML; - /* set the speed */ - cmdcfg &= ~(CC_ES_MASK | CC_HD); - /* Set to 1Gbps and full duplex by default */ - cmdcfg |= (2 << CC_ES_SHIFT); - - /* put mac in reset */ - gmac_init_reset(); - /* write register */ - writel(cmdcfg, UNIMAC0_CMD_CFG_ADDR); - /* bring mac out of reset */ - gmac_clear_reset(); - - /* set max frame lengths; account for possible vlan tag */ - writel(PKTSIZE + 32, UNIMAC0_FRM_LENGTH_ADDR); - - return 0; - -err_exit: - dma_deinit(dma); - return -1; -} - -int gmac_add(struct eth_device *dev) -{ - struct eth_info *eth = (struct eth_info *)(dev->priv); - struct eth_dma *dma = &(eth->dma); - void *tmp; - - /* - * Desc has to be 16-byte aligned. But for dcache flush it must be - * aligned to ARCH_DMA_MINALIGN. - */ - tmp = memalign(ARCH_DMA_MINALIGN, DESCP_SIZE_ALIGNED * TX_BUF_NUM); - if (tmp == NULL) { - printf("%s: Failed to allocate TX desc Buffer\n", __func__); - return -1; - } - - dma->tx_desc_aligned = (void *)tmp; - debug("TX Descriptor Buffer: %p; length: 0x%x\n", - dma->tx_desc_aligned, DESCP_SIZE_ALIGNED * TX_BUF_NUM); - - tmp = memalign(ARCH_DMA_MINALIGN, TX_BUF_SIZE_ALIGNED * TX_BUF_NUM); - if (tmp == NULL) { - printf("%s: Failed to allocate TX Data Buffer\n", __func__); - free(dma->tx_desc_aligned); - return -1; - } - dma->tx_buf = (uint8_t *)tmp; - debug("TX Data Buffer: %p; length: 0x%x\n", - dma->tx_buf, TX_BUF_SIZE_ALIGNED * TX_BUF_NUM); - - /* Desc has to be 16-byte aligned */ - tmp = memalign(ARCH_DMA_MINALIGN, DESCP_SIZE_ALIGNED * RX_BUF_NUM); - if (tmp == NULL) { - printf("%s: Failed to allocate RX Descriptor\n", __func__); - free(dma->tx_desc_aligned); - free(dma->tx_buf); - return -1; - } - dma->rx_desc_aligned = (void *)tmp; - debug("RX Descriptor Buffer: %p, length: 0x%x\n", - dma->rx_desc_aligned, DESCP_SIZE_ALIGNED * RX_BUF_NUM); - - tmp = memalign(ARCH_DMA_MINALIGN, RX_BUF_SIZE_ALIGNED * RX_BUF_NUM); - if (tmp == NULL) { - printf("%s: Failed to allocate RX Data Buffer\n", __func__); - free(dma->tx_desc_aligned); - free(dma->tx_buf); - free(dma->rx_desc_aligned); - return -1; - } - dma->rx_buf = (uint8_t *)tmp; - debug("RX Data Buffer: %p; length: 0x%x\n", - dma->rx_buf, RX_BUF_SIZE_ALIGNED * RX_BUF_NUM); - - g_dmactrlflags = 0; - - eth->phy_interface = PHY_INTERFACE_MODE_GMII; - - dma->tx_packet = gmac_tx_packet; - dma->check_tx_done = gmac_check_tx_done; - - dma->check_rx_done = gmac_check_rx_done; - - dma->enable_dma = gmac_enable_dma; - dma->disable_dma = gmac_disable_dma; - - eth->miiphy_read = gmac_miiphy_read; - eth->miiphy_write = gmac_miiphy_write; - - eth->mac_init = gmac_mac_init; - eth->disable_mac = gmac_disable; - eth->enable_mac = gmac_enable; - eth->set_mac_addr = gmac_set_mac_addr; - eth->set_mac_speed = gmac_set_speed; - - return 0; -} diff --git a/drivers/net/bcm-sf2-eth-gmac.h b/drivers/net/bcm-sf2-eth-gmac.h deleted file mode 100644 index ac5e45d4f90..00000000000 --- a/drivers/net/bcm-sf2-eth-gmac.h +++ /dev/null @@ -1,222 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright 2014 Broadcom Corporation. - */ - -#ifndef _BCM_SF2_ETH_GMAC_H_ -#define _BCM_SF2_ETH_GMAC_H_ - -#define BCM_SF2_ETH_MAC_NAME "gmac" - -#ifndef ETHHW_PORT_INT -#define ETHHW_PORT_INT 8 -#endif - -#define GMAC0_REG_BASE 0x18042000 -#define GMAC0_DEV_CTRL_ADDR GMAC0_REG_BASE -#define GMAC0_INT_STATUS_ADDR (GMAC0_REG_BASE + 0x020) -#define GMAC0_INTR_RECV_LAZY_ADDR (GMAC0_REG_BASE + 0x100) -#define GMAC0_PHY_CTRL_ADDR (GMAC0_REG_BASE + 0x188) - -#define GMAC_DMA_PTR_OFFSET 0x04 -#define GMAC_DMA_ADDR_LOW_OFFSET 0x08 -#define GMAC_DMA_ADDR_HIGH_OFFSET 0x0c -#define GMAC_DMA_STATUS0_OFFSET 0x10 -#define GMAC_DMA_STATUS1_OFFSET 0x14 - -#define GMAC0_DMA_TX_CTRL_ADDR (GMAC0_REG_BASE + 0x200) -#define GMAC0_DMA_TX_PTR_ADDR \ - (GMAC0_DMA_TX_CTRL_ADDR + GMAC_DMA_PTR_OFFSET) -#define GMAC0_DMA_TX_ADDR_LOW_ADDR \ - (GMAC0_DMA_TX_CTRL_ADDR + GMAC_DMA_ADDR_LOW_OFFSET) -#define GMAC0_DMA_TX_ADDR_HIGH_ADDR \ - (GMAC0_DMA_TX_CTRL_ADDR + GMAC_DMA_ADDR_HIGH_OFFSET) -#define GMAC0_DMA_TX_STATUS0_ADDR \ - (GMAC0_DMA_TX_CTRL_ADDR + GMAC_DMA_STATUS0_OFFSET) -#define GMAC0_DMA_TX_STATUS1_ADDR \ - (GMAC0_DMA_TX_CTRL_ADDR + GMAC_DMA_STATUS1_OFFSET) - -#define GMAC0_DMA_RX_CTRL_ADDR (GMAC0_REG_BASE + 0x220) -#define GMAC0_DMA_RX_PTR_ADDR \ - (GMAC0_DMA_RX_CTRL_ADDR + GMAC_DMA_PTR_OFFSET) -#define GMAC0_DMA_RX_ADDR_LOW_ADDR \ - (GMAC0_DMA_RX_CTRL_ADDR + GMAC_DMA_ADDR_LOW_OFFSET) -#define GMAC0_DMA_RX_ADDR_HIGH_ADDR \ - (GMAC0_DMA_RX_CTRL_ADDR + GMAC_DMA_ADDR_HIGH_OFFSET) -#define GMAC0_DMA_RX_STATUS0_ADDR \ - (GMAC0_DMA_RX_CTRL_ADDR + GMAC_DMA_STATUS0_OFFSET) -#define GMAC0_DMA_RX_STATUS1_ADDR \ - (GMAC0_DMA_RX_CTRL_ADDR + GMAC_DMA_STATUS1_OFFSET) - -#define UNIMAC0_CMD_CFG_ADDR (GMAC0_REG_BASE + 0x808) -#define UNIMAC0_MAC_MSB_ADDR (GMAC0_REG_BASE + 0x80c) -#define UNIMAC0_MAC_LSB_ADDR (GMAC0_REG_BASE + 0x810) -#define UNIMAC0_FRM_LENGTH_ADDR (GMAC0_REG_BASE + 0x814) - -#define GMAC0_IRL_FRAMECOUNT_SHIFT 24 - -/* transmit channel control */ -/* transmit enable */ -#define D64_XC_XE 0x00000001 -/* transmit suspend request */ -#define D64_XC_SE 0x00000002 -/* parity check disable */ -#define D64_XC_PD 0x00000800 -/* BurstLen bits */ -#define D64_XC_BL_MASK 0x001C0000 -#define D64_XC_BL_SHIFT 18 - -/* transmit descriptor table pointer */ -/* last valid descriptor */ -#define D64_XP_LD_MASK 0x00001fff - -/* transmit channel status */ -/* transmit state */ -#define D64_XS0_XS_MASK 0xf0000000 -#define D64_XS0_XS_SHIFT 28 -#define D64_XS0_XS_DISABLED 0x00000000 -#define D64_XS0_XS_ACTIVE 0x10000000 -#define D64_XS0_XS_IDLE 0x20000000 -#define D64_XS0_XS_STOPPED 0x30000000 -#define D64_XS0_XS_SUSP 0x40000000 - -/* receive channel control */ -/* receive enable */ -#define D64_RC_RE 0x00000001 -/* address extension bits */ -#define D64_RC_AE 0x00030000 -/* overflow continue */ -#define D64_RC_OC 0x00000400 -/* parity check disable */ -#define D64_RC_PD 0x00000800 -/* receive frame offset */ -#define D64_RC_RO_MASK 0x000000fe -#define D64_RC_RO_SHIFT 1 -/* BurstLen bits */ -#define D64_RC_BL_MASK 0x001C0000 -#define D64_RC_BL_SHIFT 18 - -/* flags for dma controller */ -/* partity enable */ -#define DMA_CTRL_PEN (1 << 0) -/* rx overflow continue */ -#define DMA_CTRL_ROC (1 << 1) - -/* receive descriptor table pointer */ -/* last valid descriptor */ -#define D64_RP_LD_MASK 0x00001fff - -/* receive channel status */ -/* current descriptor pointer */ -#define D64_RS0_CD_MASK 0x00001fff -/* receive state */ -#define D64_RS0_RS_MASK 0xf0000000 -#define D64_RS0_RS_SHIFT 28 -#define D64_RS0_RS_DISABLED 0x00000000 -#define D64_RS0_RS_ACTIVE 0x10000000 -#define D64_RS0_RS_IDLE 0x20000000 -#define D64_RS0_RS_STOPPED 0x30000000 -#define D64_RS0_RS_SUSP 0x40000000 - -/* descriptor control flags 1 */ -/* core specific flags */ -#define D64_CTRL_COREFLAGS 0x0ff00000 -/* end of descriptor table */ -#define D64_CTRL1_EOT ((uint32_t)1 << 28) -/* interrupt on completion */ -#define D64_CTRL1_IOC ((uint32_t)1 << 29) -/* end of frame */ -#define D64_CTRL1_EOF ((uint32_t)1 << 30) -/* start of frame */ -#define D64_CTRL1_SOF ((uint32_t)1 << 31) - -/* descriptor control flags 2 */ -/* buffer byte count. real data len must <= 16KB */ -#define D64_CTRL2_BC_MASK 0x00007fff -/* address extension bits */ -#define D64_CTRL2_AE 0x00030000 -#define D64_CTRL2_AE_SHIFT 16 -/* parity bit */ -#define D64_CTRL2_PARITY 0x00040000 -/* control flags in the range [27:20] are core-specific and not defined here */ -#define D64_CTRL_CORE_MASK 0x0ff00000 - -#define DC_MROR 0x00000010 -#define PC_MTE 0x00800000 - -/* command config */ -#define CC_TE 0x00000001 -#define CC_RE 0x00000002 -#define CC_ES_MASK 0x0000000c -#define CC_ES_SHIFT 2 -#define CC_PROM 0x00000010 -#define CC_PAD_EN 0x00000020 -#define CC_CF 0x00000040 -#define CC_PF 0x00000080 -#define CC_RPI 0x00000100 -#define CC_TAI 0x00000200 -#define CC_HD 0x00000400 -#define CC_HD_SHIFT 10 -#define CC_SR 0x00002000 -#define CC_ML 0x00008000 -#define CC_AE 0x00400000 -#define CC_CFE 0x00800000 -#define CC_NLC 0x01000000 -#define CC_RL 0x02000000 -#define CC_RED 0x04000000 -#define CC_PE 0x08000000 -#define CC_TPI 0x10000000 -#define CC_AT 0x20000000 - -#define I_PDEE 0x00000400 -#define I_PDE 0x00000800 -#define I_DE 0x00001000 -#define I_RDU 0x00002000 -#define I_RFO 0x00004000 -#define I_XFU 0x00008000 -#define I_RI 0x00010000 -#define I_XI0 0x01000000 -#define I_XI1 0x02000000 -#define I_XI2 0x04000000 -#define I_XI3 0x08000000 -#define I_ERRORS (I_PDEE | I_PDE | I_DE | I_RDU | I_RFO | I_XFU) -#define DEF_INTMASK (I_XI0 | I_XI1 | I_XI2 | I_XI3 | I_RI | I_ERRORS) - -#define I_INTMASK 0x0f01fcff - -#define CHIP_DRU_BASE 0x0301d000 -#define CRMU_CHIP_IO_PAD_CONTROL_ADDR (CHIP_DRU_BASE + 0x0bc) -#define SWITCH_GLOBAL_CONFIG_ADDR (CHIP_DRU_BASE + 0x194) - -#define CDRU_IOMUX_FORCE_PAD_IN_SHIFT 0 -#define CDRU_SWITCH_BYPASS_SWITCH_SHIFT 13 - -#define AMAC0_IDM_RESET_ADDR 0x18110800 -#define AMAC0_IO_CTRL_DIRECT_ADDR 0x18110408 -#define AMAC0_IO_CTRL_CLK_250_SEL_SHIFT 6 -#define AMAC0_IO_CTRL_GMII_MODE_SHIFT 5 -#define AMAC0_IO_CTRL_DEST_SYNC_MODE_EN_SHIFT 3 - -#define CHIPA_CHIP_ID_ADDR 0x18000000 -#define CHIPID (readl(CHIPA_CHIP_ID_ADDR) & 0xFFFF) -#define CHIPREV (((readl(CHIPA_CHIP_ID_ADDR) >> 16) & 0xF) -#define CHIPSKU (((readl(CHIPA_CHIP_ID_ADDR) >> 20) & 0xF) - -#define GMAC_MII_CTRL_ADDR 0x18002000 -#define GMAC_MII_CTRL_BYP_SHIFT 10 -#define GMAC_MII_CTRL_EXT_SHIFT 9 -#define GMAC_MII_DATA_ADDR 0x18002004 -#define GMAC_MII_DATA_READ_CMD 0x60020000 -#define GMAC_MII_DATA_WRITE_CMD 0x50020000 -#define GMAC_MII_BUSY_SHIFT 8 -#define GMAC_MII_PHY_ADDR_SHIFT 23 -#define GMAC_MII_PHY_REG_SHIFT 18 - -#define GMAC_RESET_DELAY 2 -#define HWRXOFF 30 -#define MAXNAMEL 8 -#define NUMTXQ 4 - -int gmac_add(struct eth_device *dev); - -#endif /* _BCM_SF2_ETH_GMAC_H_ */ diff --git a/drivers/net/bcm-sf2-eth.c b/drivers/net/bcm-sf2-eth.c deleted file mode 100644 index c10719c6b51..00000000000 --- a/drivers/net/bcm-sf2-eth.c +++ /dev/null @@ -1,274 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright 2014 Broadcom Corporation. - */ - -#include <log.h> -#include <malloc.h> -#include <net.h> -#include <config.h> -#include <linux/delay.h> -#include <linux/printk.h> - -#include <phy.h> -#include <miiphy.h> - -#include <asm/io.h> - -#include <netdev.h> -#include "bcm-sf2-eth.h" - -#if defined(CONFIG_BCM_SF2_ETH_GMAC) -#include "bcm-sf2-eth-gmac.h" -#else -#error "bcm_sf2_eth: NEED to define a MAC!" -#endif - -#define BCM_NET_MODULE_DESCRIPTION "Broadcom Starfighter2 Ethernet driver" -#define BCM_NET_MODULE_VERSION "0.1" -#define BCM_SF2_ETH_DEV_NAME "bcm_sf2" - -static const char banner[] = - BCM_NET_MODULE_DESCRIPTION " " BCM_NET_MODULE_VERSION "\n"; - -static int bcm_sf2_eth_init(struct eth_device *dev) -{ - struct eth_info *eth = (struct eth_info *)(dev->priv); - struct eth_dma *dma = &(eth->dma); - struct phy_device *phydev; - int rc = 0; - int i; - - rc = eth->mac_init(dev); - if (rc) { - pr_err("%s: Couldn't cofigure MAC!\n", __func__); - return rc; - } - - /* disable DMA */ - dma->disable_dma(dma, MAC_DMA_RX); - dma->disable_dma(dma, MAC_DMA_TX); - - eth->port_num = 0; - debug("Connecting PHY 0...\n"); - phydev = phy_connect(miiphy_get_dev_by_name(dev->name), - -1, dev, eth->phy_interface); - if (phydev != NULL) { - eth->port[0] = phydev; - eth->port_num += 1; - } else { - debug("No PHY found for port 0\n"); - } - - for (i = 0; i < eth->port_num; i++) - phy_config(eth->port[i]); - - return rc; -} - -/* - * u-boot net functions - */ - -static int bcm_sf2_eth_send(struct eth_device *dev, void *packet, int length) -{ - struct eth_dma *dma = &(((struct eth_info *)(dev->priv))->dma); - uint8_t *buf = (uint8_t *)packet; - int rc = 0; - int i = 0; - - debug("%s enter\n", __func__); - - /* load buf and start transmit */ - rc = dma->tx_packet(dma, buf, length); - if (rc) { - debug("ERROR - Tx failed\n"); - return rc; - } - - while (!(dma->check_tx_done(dma))) { - udelay(100); - debug("."); - i++; - if (i > 20) { - pr_err("%s: Tx timeout: retried 20 times\n", __func__); - rc = -1; - break; - } - } - - debug("%s exit rc(0x%x)\n", __func__, rc); - return rc; -} - -static int bcm_sf2_eth_receive(struct eth_device *dev) -{ - struct eth_dma *dma = &(((struct eth_info *)(dev->priv))->dma); - uint8_t *buf = (uint8_t *)net_rx_packets[0]; - int rcvlen; - int rc = 0; - int i = 0; - - while (1) { - /* Poll Rx queue to get a packet */ - rcvlen = dma->check_rx_done(dma, buf); - if (rcvlen < 0) { - /* No packet received */ - rc = -1; - debug("\nNO More Rx\n"); - break; - } else if ((rcvlen == 0) || (rcvlen > RX_BUF_SIZE)) { - pr_err("%s: Wrong Ethernet packet size (%d B), skip!\n", - __func__, rcvlen); - break; - } else { - debug("recieved\n"); - - /* Forward received packet to uboot network handler */ - net_process_received_packet(buf, rcvlen); - - if (++i >= PKTBUFSRX) - i = 0; - buf = net_rx_packets[i]; - } - } - - return rc; -} - -static int bcm_sf2_eth_write_hwaddr(struct eth_device *dev) -{ - struct eth_info *eth = (struct eth_info *)(dev->priv); - - printf(" ETH MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", - dev->enetaddr[0], dev->enetaddr[1], dev->enetaddr[2], - dev->enetaddr[3], dev->enetaddr[4], dev->enetaddr[5]); - - return eth->set_mac_addr(dev->enetaddr); -} - -static int bcm_sf2_eth_open(struct eth_device *dev, struct bd_info *bt) -{ - struct eth_info *eth = (struct eth_info *)(dev->priv); - struct eth_dma *dma = &(eth->dma); - int i; - - debug("Enabling BCM SF2 Ethernet.\n"); - - eth->enable_mac(); - - /* enable tx and rx DMA */ - dma->enable_dma(dma, MAC_DMA_RX); - dma->enable_dma(dma, MAC_DMA_TX); - - /* - * Need to start PHY here because link speed can change - * before each ethernet operation - */ - for (i = 0; i < eth->port_num; i++) { - if (phy_startup(eth->port[i])) { - pr_err("%s: PHY %d startup failed!\n", __func__, i); - if (i == CONFIG_BCM_SF2_ETH_DEFAULT_PORT) { - pr_err("%s: No default port %d!\n", __func__, i); - return -1; - } - } - } - - /* Set MAC speed using default port */ - i = CONFIG_BCM_SF2_ETH_DEFAULT_PORT; - debug("PHY %d: speed:%d, duplex:%d, link:%d\n", i, - eth->port[i]->speed, eth->port[i]->duplex, eth->port[i]->link); - eth->set_mac_speed(eth->port[i]->speed, eth->port[i]->duplex); - - debug("Enable Ethernet Done.\n"); - - return 0; -} - -static void bcm_sf2_eth_close(struct eth_device *dev) -{ - struct eth_info *eth = (struct eth_info *)(dev->priv); - struct eth_dma *dma = &(eth->dma); - - /* disable DMA */ - dma->disable_dma(dma, MAC_DMA_RX); - dma->disable_dma(dma, MAC_DMA_TX); - - eth->disable_mac(); -} - -int bcm_sf2_eth_register(struct bd_info *bis, u8 dev_num) -{ - struct eth_device *dev; - struct eth_info *eth; - int rc; - - dev = (struct eth_device *)malloc(sizeof(struct eth_device)); - if (dev == NULL) { - pr_err("%s: Not enough memory!\n", __func__); - return -1; - } - - eth = (struct eth_info *)malloc(sizeof(struct eth_info)); - if (eth == NULL) { - pr_err("%s: Not enough memory!\n", __func__); - return -1; - } - - printf(banner); - - memset(dev, 0, sizeof(*dev)); - sprintf(dev->name, "%s_%s-%hu", BCM_SF2_ETH_DEV_NAME, - BCM_SF2_ETH_MAC_NAME, dev_num); - - dev->priv = (void *)eth; - dev->iobase = 0; - - dev->init = bcm_sf2_eth_open; - dev->halt = bcm_sf2_eth_close; - dev->send = bcm_sf2_eth_send; - dev->recv = bcm_sf2_eth_receive; - dev->write_hwaddr = bcm_sf2_eth_write_hwaddr; - -#ifdef CONFIG_BCM_SF2_ETH_GMAC - if (gmac_add(dev)) { - free(eth); - free(dev); - pr_err("%s: Adding GMAC failed!\n", __func__); - return -1; - } -#else -#error "bcm_sf2_eth: NEED to register a MAC!" -#endif - - eth_register(dev); - -#ifdef CONFIG_CMD_MII - int retval; - struct mii_dev *mdiodev = mdio_alloc(); - - if (!mdiodev) - return -ENOMEM; - strlcpy(mdiodev->name, dev->name, MDIO_NAME_LEN); - mdiodev->read = eth->miiphy_read; - mdiodev->write = eth->miiphy_write; - - retval = mdio_register(mdiodev); - if (retval < 0) - return retval; -#endif - - /* Initialization */ - debug("Ethernet initialization ..."); - - rc = bcm_sf2_eth_init(dev); - if (rc != 0) { - pr_err("%s: configuration failed!\n", __func__); - return -1; - } - - printf("Basic ethernet functionality initialized\n"); - - return 0; -} diff --git a/drivers/net/bcm-sf2-eth.h b/drivers/net/bcm-sf2-eth.h deleted file mode 100644 index f4dbb4e1952..00000000000 --- a/drivers/net/bcm-sf2-eth.h +++ /dev/null @@ -1,65 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright 2014-2017 Broadcom. - */ - -#ifndef _BCM_SF2_ETH_H_ -#define _BCM_SF2_ETH_H_ - -#include <phy.h> - -#define RX_BUF_SIZE 2048 -/* RX_BUF_NUM must be power of 2 */ -#define RX_BUF_NUM 32 - -#define TX_BUF_SIZE 2048 -/* TX_BUF_NUM must be power of 2 */ -#define TX_BUF_NUM 2 - -/* Support 2 Ethernet ports now */ -#define BCM_ETH_MAX_PORT_NUM 2 - -enum { - MAC_DMA_TX = 1, - MAC_DMA_RX = 2 -}; - -struct eth_dma { - void *tx_desc_aligned; - void *rx_desc_aligned; - - uint8_t *tx_buf; - uint8_t *rx_buf; - - int cur_tx_index; - int cur_rx_index; - - int (*tx_packet)(struct eth_dma *dma, void *packet, int length); - bool (*check_tx_done)(struct eth_dma *dma); - - int (*check_rx_done)(struct eth_dma *dma, uint8_t *buf); - - int (*enable_dma)(struct eth_dma *dma, int dir); - int (*disable_dma)(struct eth_dma *dma, int dir); -}; - -struct eth_info { - struct eth_dma dma; - phy_interface_t phy_interface; - struct phy_device *port[BCM_ETH_MAX_PORT_NUM]; - int port_num; - - int (*miiphy_read)(struct mii_dev *bus, int phyaddr, int devad, - int reg); - int (*miiphy_write)(struct mii_dev *bus, int phyaddr, int devad, - int reg, u16 value); - - int (*mac_init)(struct eth_device *dev); - int (*enable_mac)(void); - int (*disable_mac)(void); - int (*set_mac_addr)(unsigned char *mac); - int (*set_mac_speed)(int speed, int duplex); - -}; - -#endif /* _BCM_SF2_ETH_H_ */ diff --git a/drivers/net/fsl_enetc.c b/drivers/net/fsl_enetc.c index 97cccda4519..a4ba27904bc 100644 --- a/drivers/net/fsl_enetc.c +++ b/drivers/net/fsl_enetc.c @@ -6,6 +6,7 @@ */ #include <clk.h> +#include <cpu_func.h> #include <dm.h> #include <errno.h> #include <fdt_support.h> diff --git a/drivers/net/ftgmac100.c b/drivers/net/ftgmac100.c index f5ea2e72d1b..33d1f7da3d7 100644 --- a/drivers/net/ftgmac100.c +++ b/drivers/net/ftgmac100.c @@ -546,7 +546,7 @@ static int ftgmac100_send(struct udevice *dev, void *packet, int length) return -EPERM; } - debug("%s(%x, %x)\n", __func__, (int)packet, length); + debug("%s(%p, %x)\n", __func__, packet, length); length = (length < ETH_ZLEN) ? ETH_ZLEN : length; diff --git a/drivers/net/hifemac.c b/drivers/net/hifemac.c index 90cc247b3b6..62182f922f8 100644 --- a/drivers/net/hifemac.c +++ b/drivers/net/hifemac.c @@ -9,6 +9,7 @@ #include <dm.h> #include <clk.h> +#include <cpu_func.h> #include <miiphy.h> #include <net.h> #include <reset.h> diff --git a/drivers/net/pfe_eth/Kconfig b/drivers/net/pfe_eth/Kconfig index b2724ee3e84..f5947ab5f17 100644 --- a/drivers/net/pfe_eth/Kconfig +++ b/drivers/net/pfe_eth/Kconfig @@ -1,5 +1,6 @@ menuconfig FSL_PFE bool "NXP PFE Ethernet driver" + depends on ARCH_LS1012A help This driver provides support for NXP's Packet Forwarding Engine. diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 8d88c142900..21bf983056a 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -23,7 +23,10 @@ config PHY_ANEG_TIMEOUT int "PHY auto-negotiation timeout" default 4000 help - Default PHY auto-negotiation timeout. + Value of PHY auto-negotiation timeout with the base being + "decimal" and the unit being "millisecond". This can be + overridden by the "phy_aneg_timeout" environment variable + that has the same base (decimal) and unit (millisecond). if PHY_ADDR_ENABLE config PHY_ADDR diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index d2db8d9f792..f63a13824ca 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -7,6 +7,7 @@ */ #include <config.h> #include <dm.h> +#include <env.h> #include <log.h> #include <net.h> #include <phy.h> @@ -551,14 +552,15 @@ int aquantia_config(struct phy_device *phydev) int aquantia_startup(struct phy_device *phydev) { - u32 speed; - int i = 0; + u32 speed, i = 0; int reg; phydev->duplex = DUPLEX_FULL; /* if the AN is still in progress, wait till timeout. */ if (!aquantia_link_is_up(phydev)) { + u32 aneg_timeout = env_get_ulong("phy_aneg_timeout", 10, + CONFIG_PHY_ANEG_TIMEOUT); printf("%s Waiting for PHY auto negotiation to complete", phydev->dev->name); do { @@ -566,9 +568,9 @@ int aquantia_startup(struct phy_device *phydev) if ((i++ % 500) == 0) printf("."); } while (!aquantia_link_is_up(phydev) && - i < (4 * CONFIG_PHY_ANEG_TIMEOUT)); + i < (4 * aneg_timeout)); - if (i > CONFIG_PHY_ANEG_TIMEOUT) + if (i > aneg_timeout) printf(" TIMEOUT !\n"); } diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index e6fed8c41d7..9702d042296 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -9,6 +9,7 @@ */ #include <console.h> #include <dm.h> +#include <env.h> #include <log.h> #include <malloc.h> #include <net.h> @@ -242,7 +243,9 @@ int genphy_update_link(struct phy_device *phydev) if ((phydev->autoneg == AUTONEG_ENABLE) && !(mii_reg & BMSR_ANEGCOMPLETE)) { - int i = 0; + u32 i = 0; + u32 aneg_timeout = env_get_ulong("phy_aneg_timeout", 10, + CONFIG_PHY_ANEG_TIMEOUT); printf("%s Waiting for PHY auto negotiation to complete", phydev->dev->name); @@ -250,7 +253,7 @@ int genphy_update_link(struct phy_device *phydev) /* * Timeout reached ? */ - if (i > (CONFIG_PHY_ANEG_TIMEOUT / 50)) { + if (i > (aneg_timeout / 50)) { printf(" TIMEOUT !\n"); phydev->link = 0; return -ETIMEDOUT; diff --git a/drivers/net/qe/Kconfig b/drivers/net/qe/Kconfig index e795e913d42..34de2390310 100644 --- a/drivers/net/qe/Kconfig +++ b/drivers/net/qe/Kconfig @@ -4,5 +4,6 @@ config QE_UEC bool "NXP QE UEC Ethernet controller" + depends on PPC help This driver supports the NXP QE UEC ethernet controller diff --git a/drivers/net/ti/Kconfig b/drivers/net/ti/Kconfig index ddfa95a0b7e..52267339de0 100644 --- a/drivers/net/ti/Kconfig +++ b/drivers/net/ti/Kconfig @@ -4,6 +4,7 @@ config DRIVER_TI_CPSW bool "TI Common Platform Ethernet Switch" + depends on ARCH_OMAP2PLUS select PHYLIB help This driver supports the TI three port switch gigabit ethernet @@ -11,6 +12,7 @@ config DRIVER_TI_CPSW config DRIVER_TI_EMAC bool "TI Davinci EMAC" + depends on ARCH_DAVINCI || ARCH_OMAP2PLUS help Support for davinci emac @@ -22,6 +24,7 @@ config DRIVER_TI_EMAC_USE_RMII config DRIVER_TI_KEYSTONE_NET bool "TI Keystone 2 Ethernet" + depends on ARCH_KEYSTONE help This driver supports the TI Keystone 2 Ethernet subsystem diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c index 4d87e2d1f36..c8038ddef1b 100644 --- a/drivers/net/xilinx_axi_emac.c +++ b/drivers/net/xilinx_axi_emac.c @@ -11,6 +11,7 @@ #include <display_options.h> #include <dm.h> #include <dm/device_compat.h> +#include <env.h> #include <log.h> #include <net.h> #include <malloc.h> @@ -343,6 +344,8 @@ static int axiemac_phy_init(struct udevice *dev) static int pcs_pma_startup(struct axidma_priv *priv) { + u32 aneg_timeout = env_get_ulong("phy_aneg_timeout", 10, + CONFIG_PHY_ANEG_TIMEOUT); u32 rc, retry_cnt = 0; u16 mii_reg; @@ -361,7 +364,7 @@ static int pcs_pma_startup(struct axidma_priv *priv) * and the external PHY is not obtained. */ debug("axiemac: waiting for link status of the PCS/PMA PHY"); - while (retry_cnt * 10 < CONFIG_PHY_ANEG_TIMEOUT) { + while (retry_cnt * 10 < aneg_timeout) { rc = phyread(priv, priv->pcsaddr, MII_BMSR, &mii_reg); if ((mii_reg & BMSR_LSTATUS) && mii_reg != 0xffff && !rc) { debug(".Done\n"); diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig index 5f5218bd8b5..ebf5d828cb0 100644 --- a/drivers/power/domain/Kconfig +++ b/drivers/power/domain/Kconfig @@ -18,6 +18,14 @@ config APPLE_PMGR_POWER_DOMAIN This driver is needed to power on parts of the SoC that have not been powered on by previous boot stages. +config AGILEX5_PMGR_POWER_DOMAIN + bool "Enable the Agilex5 PMGR power domain driver" + depends on SPL_POWER_DOMAIN + help + Enable support for power gating peripherals' SRAM specified in + the handoff data values obtained from the bitstream to reduce + power consumption. + config BCM6328_POWER_DOMAIN bool "Enable the BCM6328 power domain driver" depends on POWER_DOMAIN && ARCH_BMIPS diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile index 4d20c97d26c..8e03f620437 100644 --- a/drivers/power/domain/Makefile +++ b/drivers/power/domain/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_$(PHASE_)POWER_DOMAIN) += power-domain-uclass.o obj-$(CONFIG_APPLE_PMGR_POWER_DOMAIN) += apple-pmgr.o +obj-$(CONFIG_AGILEX5_PMGR_POWER_DOMAIN) += altr-pmgr-agilex5.o obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o obj-$(CONFIG_IMX8_POWER_DOMAIN) += imx8-power-domain-legacy.o imx8-power-domain.o obj-$(CONFIG_IMX8M_POWER_DOMAIN) += imx8m-power-domain.o diff --git a/drivers/power/domain/altr-pmgr-agilex5.c b/drivers/power/domain/altr-pmgr-agilex5.c new file mode 100644 index 00000000000..257e8b234fd --- /dev/null +++ b/drivers/power/domain/altr-pmgr-agilex5.c @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2025 Altera Corporation <www.altera.com> + */ + +#include <dm.h> +#include <power-domain-uclass.h> +#include <asm/io.h> +#include <asm/arch/handoff_soc64.h> +#include <linux/bitfield.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <time.h> + +#define PSS_FWENCTL 0x44 +#define PSS_PGENCTL 0x48 +#define PSS_PGSTAT 0x4c + +#define DATA_MASK GENMASK(7, 0) +#define TIMEOUT_MS 1000 + +static int wait_verify_fsm(u16 timeout_ms, uintptr_t base_addr, u32 peripheral_handoff) +{ + u32 data = 0; + u32 pgstat = 0; + ulong start = get_timer(0); + + /* Wait FSM ready */ + do { + data = FIELD_GET(DATA_MASK, readl(base_addr + PSS_PGSTAT)); + if (data != 0) + break; + } while (get_timer(start) < timeout_ms); + + if (get_timer(start) >= timeout_ms) + return -ETIMEDOUT; + + /* Verify PSS SRAM power gated */ + pgstat = FIELD_GET(DATA_MASK, readl(base_addr + PSS_PGSTAT)); + if (pgstat != FIELD_GET(DATA_MASK, peripheral_handoff)) + return -EPERM; + + return 0; +} + +static int pss_sram_power_off(uintptr_t base_addr, u32 *handoff_table) +{ + u32 peripheral_handoff; + + /* Get PSS SRAM handoff data */ + peripheral_handoff = handoff_table[0]; + + /* Enable firewall for PSS SRAM */ + setbits_le32(base_addr + PSS_FWENCTL, peripheral_handoff); + + /* Wait */ + udelay(1); + + /* Power gating PSS SRAM */ + setbits_le32(base_addr + PSS_PGENCTL, peripheral_handoff); + + return wait_verify_fsm(TIMEOUT_MS, base_addr, peripheral_handoff); +} + +static int altera_pmgr_off(struct power_domain *power_domain) +{ + fdt_addr_t base_addr = dev_read_addr(power_domain->dev); + u32 handoff_table[SOC64_HANDOFF_PERI_LEN]; + int ret; + + /* Read handoff data for peripherals configuration */ + ret = socfpga_handoff_read((void *)SOC64_HANDOFF_PERI, handoff_table, + SOC64_HANDOFF_PERI_LEN); + if (ret) { + debug("%s: handoff data read failed. ret: %d\n", __func__, ret); + return ret; + } + + pss_sram_power_off(base_addr, handoff_table); + + return 0; +} + +static int altera_pmgr_probe(struct udevice *dev) +{ + struct power_domain *power_domain = dev_get_priv(dev); + + if (!power_domain) + return -EINVAL; + + power_domain->dev = dev; + + return altera_pmgr_off(power_domain); +} + +static const struct udevice_id altera_pmgr_ids[] = { + { .compatible = "altr,pmgr-agilex5" }, + { /* sentinel */ } +}; + +static struct power_domain_ops altera_pmgr_ops = { + .off = altera_pmgr_off, +}; + +U_BOOT_DRIVER(altr_pmgr) = { + .name = "altr_pmgr", + .id = UCLASS_POWER_DOMAIN, + .of_match = altera_pmgr_ids, + .ops = &altera_pmgr_ops, + .probe = altera_pmgr_probe, + .priv_auto = sizeof(struct power_domain), +}; diff --git a/drivers/qe/Kconfig b/drivers/qe/Kconfig index 89a75c175b0..22ed80bfc66 100644 --- a/drivers/qe/Kconfig +++ b/drivers/qe/Kconfig @@ -11,6 +11,7 @@ config QE config U_QE bool "Enable support for U QUICC Engine" + depends on PPC || ARCH_LS1012A || ARCH_LS1021A || ARCH_LS1043A default y if (ARCH_LS1021A && !SD_BOOT && !NAND_BOOT && !QSPI_BOOT) \ || (TARGET_T1024QDS) \ || (TARGET_T1024RDB) \ diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index a3513f0a3ef..1ae36b5a348 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -351,6 +351,8 @@ config MTK_SPIM config MVEBU_A3700_SPI bool "Marvell Armada 3700 SPI driver" + depends on ARCH_MVEBU && ARM64 + select CLK_MVEBU select CLK_ARMADA_3720 help Enable the Marvell Armada 3700 SPI driver. This driver can be diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 99c6649e417..daf2240ffd9 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -112,6 +112,7 @@ config USB_KEYBOARD config USB_ONBOARD_HUB bool "Onboard USB hub support" depends on DM_USB + select DEVRES ---help--- Say Y here if you want to support discrete onboard USB hubs that don't require an additional control bus for initialization, but diff --git a/drivers/virtio/virtio_net.c b/drivers/virtio/virtio_net.c index 0e5367a085e..71e4d251396 100644 --- a/drivers/virtio/virtio_net.c +++ b/drivers/virtio/virtio_net.c @@ -128,6 +128,7 @@ static int virtio_net_free_pkt(struct udevice *dev, uchar *packet, int length) /* Put the buffer back to the rx ring */ virtqueue_add(priv->rx_vq, sgs, 0, 1); + virtqueue_kick(priv->rx_vq); return 0; } diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index e9ea874d0e3..56290b32bd9 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -15,6 +15,7 @@ config WATCHDOG_AUTOSTART bool "Automatically start watchdog timer" depends on WDT default n if ARCH_SUNXI + default n if ARCH_STM32MP default y help Automatically start watchdog timer and start servicing it during diff --git a/drivers/watchdog/arm_smc_wdt.c b/drivers/watchdog/arm_smc_wdt.c index 0ea44445700..f6854aa9ac9 100644 --- a/drivers/watchdog/arm_smc_wdt.c +++ b/drivers/watchdog/arm_smc_wdt.c @@ -46,6 +46,8 @@ static int smcwd_call(struct udevice *dev, enum smcwd_call call, return -ENODEV; if (res->a0 == PSCI_RET_INVALID_PARAMS) return -EINVAL; + if (res->a0 == PSCI_RET_DISABLED) + return -ENODATA; if (res->a0 != PSCI_RET_SUCCESS) return -EIO; @@ -99,6 +101,21 @@ static int smcwd_probe(struct udevice *dev) priv->min_timeout = res.a1; priv->max_timeout = res.a2; + /* If already started, then force u-boot to use it */ + err = smcwd_call(dev, SMCWD_GET_TIMELEFT, 0, NULL); + switch (err) { + case 0: + dev_dbg(dev, "Already started\n"); + wdt_set_force_autostart(dev); + break; + case -ENODATA: + dev_dbg(dev, "Not already started\n"); + break; + default: + /* Optional SMCWD_GET_TIMELEFT not implemented */ + break; + } + return 0; } diff --git a/drivers/watchdog/stm32mp_wdt.c b/drivers/watchdog/stm32mp_wdt.c index 97ab8cfe7ab..0712524b4a8 100644 --- a/drivers/watchdog/stm32mp_wdt.c +++ b/drivers/watchdog/stm32mp_wdt.c @@ -21,11 +21,13 @@ #define IWDG_PR 0x04 /* Prescaler Register */ #define IWDG_RLR 0x08 /* ReLoad Register */ #define IWDG_SR 0x0C /* Status Register */ +#define IWDG_VERR 0x3F4 /* Version Register */ /* IWDG_KR register bit mask */ #define KR_KEY_RELOAD 0xAAAA /* Reload counter enable */ #define KR_KEY_ENABLE 0xCCCC /* Peripheral enable */ #define KR_KEY_EWA 0x5555 /* Write access enable */ +#define KR_KEY_DWA 0x0000 /* Write access disable*/ /* IWDG_PR register bit values */ #define PR_256 0x06 /* Prescaler set to 256 */ @@ -36,10 +38,17 @@ /* IWDG_SR register bit values */ #define SR_PVU BIT(0) /* Watchdog prescaler value update */ #define SR_RVU BIT(1) /* Watchdog counter reload value update */ +#define SR_ONF BIT(8) /* Watchdog enable status bit */ + +/* IWDG Compatibility */ +#define ONF_MIN_VER 0x31 + +#define TIMEOUT_US 10000 struct stm32mp_wdt_priv { fdt_addr_t base; /* registers addr in physical memory */ unsigned long wdt_clk_rate; /* Watchdog dedicated clock rate */ + unsigned int hw_version; /* Peripheral version */ }; static int stm32mp_wdt_reset(struct udevice *dev) @@ -90,6 +99,7 @@ static int stm32mp_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) static int stm32mp_wdt_probe(struct udevice *dev) { struct stm32mp_wdt_priv *priv = dev_get_priv(dev); + u32 rlr, sr; struct clk clk; int ret; @@ -115,6 +125,29 @@ static int stm32mp_wdt_probe(struct udevice *dev) priv->wdt_clk_rate = clk_get_rate(&clk); + priv->hw_version = readl(priv->base + IWDG_VERR); + + if (priv->hw_version >= ONF_MIN_VER) { + if (readl(priv->base + IWDG_SR) & SR_ONF) + wdt_set_force_autostart(dev); + } else { + /* + * Workaround for old versions without IWDG_SR_ONF bit: + * - write in IWDG_RLR_OFFSET + * - wait for sync + * - if sync succeeds, then iwdg is running + */ + writel(KR_KEY_EWA, priv->base + IWDG_KR); + rlr = readl(priv->base + IWDG_RLR); + writel(rlr, priv->base + IWDG_RLR); + ret = readl_poll_timeout(priv->base + IWDG_SR, sr, sr & SR_RVU, + TIMEOUT_US); + if (!ret) + wdt_set_force_autostart(dev); + + writel(KR_KEY_DWA, priv->base + IWDG_KR); + } + dev_dbg(dev, "IWDG init done\n"); return 0; diff --git a/drivers/watchdog/wdt-uclass.c b/drivers/watchdog/wdt-uclass.c index 10be334e9ed..b32590069d9 100644 --- a/drivers/watchdog/wdt-uclass.c +++ b/drivers/watchdog/wdt-uclass.c @@ -46,6 +46,15 @@ struct wdt_priv { struct cyclic_info cyclic; }; +int wdt_set_force_autostart(struct udevice *dev) +{ + struct wdt_priv *priv = dev_get_uclass_priv(dev); + + priv->autostart = true; + + return 0; +} + static void wdt_cyclic(struct cyclic_info *c) { struct wdt_priv *priv = container_of(c, struct wdt_priv, cyclic); |