diff options
40 files changed, 564 insertions, 607 deletions
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 71a7f8dcee0..57125761844 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -679,15 +679,6 @@ config MMC_SUNXI_SLOT_EXTRA slot or emmc on mmc1 - mmc3. Setting this to 1, 2 or 3 will enable support for this. -config INITIAL_USB_SCAN_DELAY - int "delay initial usb scan by x ms to allow builtin devices to init" - default 0 - ---help--- - Some boards have on board usb devices which need longer than the - USB spec's 1 second to connect from board powerup. Set this config - option to a non 0 value to add an extra delay before the first usb - bus scan. - config USB0_VBUS_PIN string "Vbus enable pin for usb0 (otg)" default "" @@ -850,8 +841,9 @@ config VIDEO_LCD_DCLK_PHASE int "LCD panel display clock phase" depends on VIDEO_SUNXI || DM_VIDEO default 1 + range 0 3 ---help--- - Select LCD panel display clock phase shift, range 0-3. + Select LCD panel display clock phase shift config VIDEO_LCD_POWER string "LCD panel power enable pin" @@ -294,6 +294,12 @@ static int do_spi_flash_read_write(int argc, char *const argv[]) return 1; } + if (strncmp(argv[0], "read", 4) != 0 && flash->flash_is_unlocked && + !flash->flash_is_unlocked(flash, offset, len)) { + printf("ERROR: flash area is locked\n"); + return 1; + } + buf = map_physmem(addr, len, MAP_WRBACK); if (!buf && addr) { puts("Failed to map physical memory\n"); @@ -350,6 +356,12 @@ static int do_spi_flash_erase(int argc, char *const argv[]) return 1; } + if (flash->flash_is_unlocked && + !flash->flash_is_unlocked(flash, offset, len)) { + printf("ERROR: flash area is locked\n"); + return 1; + } + ret = spi_flash_erase(flash, offset, size); printf("SF: %zu bytes @ %#x Erased: ", (size_t)size, (u32)offset); if (ret) diff --git a/common/spl/spl_spi.c b/common/spl/spl_spi.c index 3eef2f8d683..d959ad11458 100644 --- a/common/spl/spl_spi.c +++ b/common/spl/spl_spi.c @@ -172,6 +172,11 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, spl_image->size, (void *)spl_image->load_addr); } + if (IS_ENABLED(CONFIG_SPI_FLASH_SOFT_RESET)) { + err = spi_nor_remove(flash); + if (err) + return err; + } } return err; diff --git a/configs/licheepi_nano_defconfig b/configs/licheepi_nano_defconfig index 0252763c776..30c569dbb6c 100644 --- a/configs/licheepi_nano_defconfig +++ b/configs/licheepi_nano_defconfig @@ -13,3 +13,6 @@ CONFIG_SPL_SPI_SUNXI=y CONFIG_SPL_STACK=0x8000 CONFIG_SYS_PBSIZE=1024 # CONFIG_SYSRESET is not set +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_SPI_FLASH_XTX=y +CONFIG_SPI=y diff --git a/configs/orangepi_zero_defconfig b/configs/orangepi_zero_defconfig index b5ff84aaf67..b6de0b9aa26 100644 --- a/configs/orangepi_zero_defconfig +++ b/configs/orangepi_zero_defconfig @@ -10,6 +10,7 @@ CONFIG_SPL_SPI_SUNXI=y CONFIG_CONSOLE_MUX=y CONFIG_SPL_STACK=0x8000 CONFIG_SYS_PBSIZE=1024 +CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_WINBOND=y CONFIG_SUN8I_EMAC=y CONFIG_SPI=y diff --git a/drivers/clk/sunxi/clk_a10.c b/drivers/clk/sunxi/clk_a10.c index db92848aafd..abd4e8b7389 100644 --- a/drivers/clk/sunxi/clk_a10.c +++ b/drivers/clk/sunxi/clk_a10.c @@ -64,30 +64,9 @@ static struct ccu_reset a10_resets[] = { [RST_USB_PHY2] = RESET(0x0cc, BIT(2)), }; -static const struct ccu_desc a10_ccu_desc = { +const struct ccu_desc a10_ccu_desc = { .gates = a10_gates, .resets = a10_resets, -}; - -static int a10_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(a10_resets)); -} - -static const struct udevice_id a10_ccu_ids[] = { - { .compatible = "allwinner,sun4i-a10-ccu", - .data = (ulong)&a10_ccu_desc }, - { .compatible = "allwinner,sun7i-a20-ccu", - .data = (ulong)&a10_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun4i_a10) = { - .name = "sun4i_a10_ccu", - .id = UCLASS_CLK, - .of_match = a10_ccu_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = a10_clk_bind, + .num_gates = ARRAY_SIZE(a10_gates), + .num_resets = ARRAY_SIZE(a10_resets), }; diff --git a/drivers/clk/sunxi/clk_a10s.c b/drivers/clk/sunxi/clk_a10s.c index 0c6564ef3b6..e486cedd48d 100644 --- a/drivers/clk/sunxi/clk_a10s.c +++ b/drivers/clk/sunxi/clk_a10s.c @@ -49,30 +49,9 @@ static struct ccu_reset a10s_resets[] = { [RST_USB_PHY1] = RESET(0x0cc, BIT(1)), }; -static const struct ccu_desc a10s_ccu_desc = { +const struct ccu_desc a10s_ccu_desc = { .gates = a10s_gates, .resets = a10s_resets, -}; - -static int a10s_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(a10s_resets)); -} - -static const struct udevice_id a10s_ccu_ids[] = { - { .compatible = "allwinner,sun5i-a10s-ccu", - .data = (ulong)&a10s_ccu_desc }, - { .compatible = "allwinner,sun5i-a13-ccu", - .data = (ulong)&a10s_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun5i_a10s) = { - .name = "sun5i_a10s_ccu", - .id = UCLASS_CLK, - .of_match = a10s_ccu_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = a10s_clk_bind, + .num_gates = ARRAY_SIZE(a10s_gates), + .num_resets = ARRAY_SIZE(a10s_resets), }; diff --git a/drivers/clk/sunxi/clk_a23.c b/drivers/clk/sunxi/clk_a23.c index 0280fb51e2d..d94fecadd59 100644 --- a/drivers/clk/sunxi/clk_a23.c +++ b/drivers/clk/sunxi/clk_a23.c @@ -68,30 +68,9 @@ static struct ccu_reset a23_resets[] = { [RST_BUS_UART4] = RESET(0x2d8, BIT(20)), }; -static const struct ccu_desc a23_ccu_desc = { +const struct ccu_desc a23_ccu_desc = { .gates = a23_gates, .resets = a23_resets, -}; - -static int a23_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(a23_resets)); -} - -static const struct udevice_id a23_clk_ids[] = { - { .compatible = "allwinner,sun8i-a23-ccu", - .data = (ulong)&a23_ccu_desc }, - { .compatible = "allwinner,sun8i-a33-ccu", - .data = (ulong)&a23_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun8i_a23) = { - .name = "sun8i_a23_ccu", - .id = UCLASS_CLK, - .of_match = a23_clk_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = a23_clk_bind, + .num_gates = ARRAY_SIZE(a23_gates), + .num_resets = ARRAY_SIZE(a23_resets), }; diff --git a/drivers/clk/sunxi/clk_a31.c b/drivers/clk/sunxi/clk_a31.c index 26d25f32408..360658912dd 100644 --- a/drivers/clk/sunxi/clk_a31.c +++ b/drivers/clk/sunxi/clk_a31.c @@ -89,28 +89,9 @@ static struct ccu_reset a31_resets[] = { [RST_APB2_UART5] = RESET(0x2d8, BIT(21)), }; -static const struct ccu_desc a31_ccu_desc = { +const struct ccu_desc a31_ccu_desc = { .gates = a31_gates, .resets = a31_resets, -}; - -static int a31_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(a31_resets)); -} - -static const struct udevice_id a31_clk_ids[] = { - { .compatible = "allwinner,sun6i-a31-ccu", - .data = (ulong)&a31_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun6i_a31) = { - .name = "sun6i_a31_ccu", - .id = UCLASS_CLK, - .of_match = a31_clk_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = a31_clk_bind, + .num_gates = ARRAY_SIZE(a31_gates), + .num_resets = ARRAY_SIZE(a31_resets), }; diff --git a/drivers/clk/sunxi/clk_a31_r.c b/drivers/clk/sunxi/clk_a31_r.c index 1f08ea956f9..fa6887fa756 100644 --- a/drivers/clk/sunxi/clk_a31_r.c +++ b/drivers/clk/sunxi/clk_a31_r.c @@ -28,32 +28,9 @@ static struct ccu_reset a31_r_resets[] = { [RST_APB0_I2C] = RESET(0x0b0, BIT(6)), }; -static const struct ccu_desc a31_r_ccu_desc = { +const struct ccu_desc a31_r_ccu_desc = { .gates = a31_r_gates, .resets = a31_r_resets, -}; - -static int a31_r_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(a31_r_resets)); -} - -static const struct udevice_id a31_r_clk_ids[] = { - { .compatible = "allwinner,sun8i-a83t-r-ccu", - .data = (ulong)&a31_r_ccu_desc }, - { .compatible = "allwinner,sun8i-h3-r-ccu", - .data = (ulong)&a31_r_ccu_desc }, - { .compatible = "allwinner,sun50i-a64-r-ccu", - .data = (ulong)&a31_r_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun6i_a31_r) = { - .name = "sun6i_a31_r_ccu", - .id = UCLASS_CLK, - .of_match = a31_r_clk_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = a31_r_clk_bind, + .num_gates = ARRAY_SIZE(a31_r_gates), + .num_resets = ARRAY_SIZE(a31_r_resets), }; diff --git a/drivers/clk/sunxi/clk_a64.c b/drivers/clk/sunxi/clk_a64.c index cbb9168edb9..8c81b1ac453 100644 --- a/drivers/clk/sunxi/clk_a64.c +++ b/drivers/clk/sunxi/clk_a64.c @@ -77,28 +77,9 @@ static const struct ccu_reset a64_resets[] = { [RST_BUS_UART4] = RESET(0x2d8, BIT(20)), }; -static const struct ccu_desc a64_ccu_desc = { +const struct ccu_desc a64_ccu_desc = { .gates = a64_gates, .resets = a64_resets, -}; - -static int a64_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(a64_resets)); -} - -static const struct udevice_id a64_ccu_ids[] = { - { .compatible = "allwinner,sun50i-a64-ccu", - .data = (ulong)&a64_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun50i_a64) = { - .name = "sun50i_a64_ccu", - .id = UCLASS_CLK, - .of_match = a64_ccu_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = a64_clk_bind, + .num_gates = ARRAY_SIZE(a64_gates), + .num_resets = ARRAY_SIZE(a64_resets), }; diff --git a/drivers/clk/sunxi/clk_a80.c b/drivers/clk/sunxi/clk_a80.c index 1ee1f99a8f4..3c9eb143167 100644 --- a/drivers/clk/sunxi/clk_a80.c +++ b/drivers/clk/sunxi/clk_a80.c @@ -74,40 +74,16 @@ static const struct ccu_reset a80_mmc_resets[] = { [3] = GATE(0xc, BIT(18)), }; -static const struct ccu_desc a80_ccu_desc = { +const struct ccu_desc a80_ccu_desc = { .gates = a80_gates, .resets = a80_resets, + .num_gates = ARRAY_SIZE(a80_gates), + .num_resets = ARRAY_SIZE(a80_resets), }; -static const struct ccu_desc a80_mmc_clk_desc = { +const struct ccu_desc a80_mmc_clk_desc = { .gates = a80_mmc_gates, .resets = a80_mmc_resets, -}; - -static int a80_clk_bind(struct udevice *dev) -{ - ulong count = ARRAY_SIZE(a80_resets); - - if (device_is_compatible(dev, "allwinner,sun9i-a80-mmc-config-clk")) - count = ARRAY_SIZE(a80_mmc_resets); - - return sunxi_reset_bind(dev, count); -} - -static const struct udevice_id a80_ccu_ids[] = { - { .compatible = "allwinner,sun9i-a80-ccu", - .data = (ulong)&a80_ccu_desc }, - { .compatible = "allwinner,sun9i-a80-mmc-config-clk", - .data = (ulong)&a80_mmc_clk_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun9i_a80) = { - .name = "sun9i_a80_ccu", - .id = UCLASS_CLK, - .of_match = a80_ccu_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = a80_clk_bind, + .num_gates = ARRAY_SIZE(a80_mmc_gates), + .num_resets = ARRAY_SIZE(a80_mmc_resets), }; diff --git a/drivers/clk/sunxi/clk_a83t.c b/drivers/clk/sunxi/clk_a83t.c index 4b57434cfaa..3562da61d14 100644 --- a/drivers/clk/sunxi/clk_a83t.c +++ b/drivers/clk/sunxi/clk_a83t.c @@ -72,28 +72,9 @@ static struct ccu_reset a83t_resets[] = { [RST_BUS_UART4] = RESET(0x2d8, BIT(20)), }; -static const struct ccu_desc a83t_ccu_desc = { +const struct ccu_desc a83t_ccu_desc = { .gates = a83t_gates, .resets = a83t_resets, -}; - -static int a83t_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(a83t_resets)); -} - -static const struct udevice_id a83t_clk_ids[] = { - { .compatible = "allwinner,sun8i-a83t-ccu", - .data = (ulong)&a83t_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun8i_a83t) = { - .name = "sun8i_a83t_ccu", - .id = UCLASS_CLK, - .of_match = a83t_clk_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = a83t_clk_bind, + .num_gates = ARRAY_SIZE(a83t_gates), + .num_resets = ARRAY_SIZE(a83t_resets), }; diff --git a/drivers/clk/sunxi/clk_f1c100s.c b/drivers/clk/sunxi/clk_f1c100s.c index 72cf8a6e5c0..7b4c3ce5176 100644 --- a/drivers/clk/sunxi/clk_f1c100s.c +++ b/drivers/clk/sunxi/clk_f1c100s.c @@ -47,28 +47,9 @@ static struct ccu_reset f1c100s_resets[] = { [RST_BUS_UART2] = RESET(0x2d0, BIT(22)), }; -static const struct ccu_desc f1c100s_ccu_desc = { +const struct ccu_desc f1c100s_ccu_desc = { .gates = f1c100s_gates, .resets = f1c100s_resets, -}; - -static int f1c100s_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(f1c100s_resets)); -} - -static const struct udevice_id f1c100s_clk_ids[] = { - { .compatible = "allwinner,suniv-f1c100s-ccu", - .data = (ulong)&f1c100s_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_suniv_f1c100s) = { - .name = "suniv_f1c100s_ccu", - .id = UCLASS_CLK, - .of_match = f1c100s_clk_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = f1c100s_clk_bind, + .num_gates = ARRAY_SIZE(f1c100s_gates), + .num_resets = ARRAY_SIZE(f1c100s_resets), }; diff --git a/drivers/clk/sunxi/clk_h3.c b/drivers/clk/sunxi/clk_h3.c index 08a830bd188..17ab3b5c278 100644 --- a/drivers/clk/sunxi/clk_h3.c +++ b/drivers/clk/sunxi/clk_h3.c @@ -90,30 +90,9 @@ static struct ccu_reset h3_resets[] = { [RST_BUS_UART3] = RESET(0x2d8, BIT(19)), }; -static const struct ccu_desc h3_ccu_desc = { +const struct ccu_desc h3_ccu_desc = { .gates = h3_gates, .resets = h3_resets, -}; - -static int h3_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(h3_resets)); -} - -static const struct udevice_id h3_ccu_ids[] = { - { .compatible = "allwinner,sun8i-h3-ccu", - .data = (ulong)&h3_ccu_desc }, - { .compatible = "allwinner,sun50i-h5-ccu", - .data = (ulong)&h3_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun8i_h3) = { - .name = "sun8i_h3_ccu", - .id = UCLASS_CLK, - .of_match = h3_ccu_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = h3_clk_bind, + .num_gates = ARRAY_SIZE(h3_gates), + .num_resets = ARRAY_SIZE(h3_resets), }; diff --git a/drivers/clk/sunxi/clk_h6.c b/drivers/clk/sunxi/clk_h6.c index b3202342932..041bc5e80ed 100644 --- a/drivers/clk/sunxi/clk_h6.c +++ b/drivers/clk/sunxi/clk_h6.c @@ -91,28 +91,9 @@ static struct ccu_reset h6_resets[] = { [RST_BUS_OTG] = RESET(0xa8c, BIT(24)), }; -static const struct ccu_desc h6_ccu_desc = { +const struct ccu_desc h6_ccu_desc = { .gates = h6_gates, .resets = h6_resets, -}; - -static int h6_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(h6_resets)); -} - -static const struct udevice_id h6_ccu_ids[] = { - { .compatible = "allwinner,sun50i-h6-ccu", - .data = (ulong)&h6_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun50i_h6) = { - .name = "sun50i_h6_ccu", - .id = UCLASS_CLK, - .of_match = h6_ccu_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = h6_clk_bind, + .num_gates = ARRAY_SIZE(h6_gates), + .num_resets = ARRAY_SIZE(h6_resets), }; diff --git a/drivers/clk/sunxi/clk_h616.c b/drivers/clk/sunxi/clk_h616.c index 80099727def..964636d7281 100644 --- a/drivers/clk/sunxi/clk_h616.c +++ b/drivers/clk/sunxi/clk_h616.c @@ -109,28 +109,9 @@ static struct ccu_reset h616_resets[] = { [RST_BUS_OTG] = RESET(0xa8c, BIT(24)), }; -static const struct ccu_desc h616_ccu_desc = { +const struct ccu_desc h616_ccu_desc = { .gates = h616_gates, .resets = h616_resets, -}; - -static int h616_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(h616_resets)); -} - -static const struct udevice_id h616_ccu_ids[] = { - { .compatible = "allwinner,sun50i-h616-ccu", - .data = (ulong)&h616_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun50i_h616) = { - .name = "sun50i_h616_ccu", - .id = UCLASS_CLK, - .of_match = h616_ccu_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = h616_clk_bind, + .num_gates = ARRAY_SIZE(h616_gates), + .num_resets = ARRAY_SIZE(h616_resets), }; diff --git a/drivers/clk/sunxi/clk_h6_r.c b/drivers/clk/sunxi/clk_h6_r.c index c592886a258..ddcb3dae30a 100644 --- a/drivers/clk/sunxi/clk_h6_r.c +++ b/drivers/clk/sunxi/clk_h6_r.c @@ -34,30 +34,9 @@ static struct ccu_reset h6_r_resets[] = { [RST_R_APB1_W1] = RESET(0x1ec, BIT(16)), }; -static const struct ccu_desc h6_r_ccu_desc = { +const struct ccu_desc h6_r_ccu_desc = { .gates = h6_r_gates, .resets = h6_r_resets, -}; - -static int h6_r_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(h6_r_resets)); -} - -static const struct udevice_id h6_r_clk_ids[] = { - { .compatible = "allwinner,sun50i-h6-r-ccu", - .data = (ulong)&h6_r_ccu_desc }, - { .compatible = "allwinner,sun50i-h616-r-ccu", - .data = (ulong)&h6_r_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun50i_h6_r) = { - .name = "sun50i_h6_r_ccu", - .id = UCLASS_CLK, - .of_match = h6_r_clk_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = h6_r_clk_bind, + .num_gates = ARRAY_SIZE(h6_r_gates), + .num_resets = ARRAY_SIZE(h6_r_resets), }; diff --git a/drivers/clk/sunxi/clk_r40.c b/drivers/clk/sunxi/clk_r40.c index 45633a2a524..ef743d65b7f 100644 --- a/drivers/clk/sunxi/clk_r40.c +++ b/drivers/clk/sunxi/clk_r40.c @@ -99,28 +99,9 @@ static struct ccu_reset r40_resets[] = { [RST_BUS_UART7] = RESET(0x2d8, BIT(23)), }; -static const struct ccu_desc r40_ccu_desc = { +const struct ccu_desc r40_ccu_desc = { .gates = r40_gates, .resets = r40_resets, -}; - -static int r40_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(r40_resets)); -} - -static const struct udevice_id r40_clk_ids[] = { - { .compatible = "allwinner,sun8i-r40-ccu", - .data = (ulong)&r40_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun8i_r40) = { - .name = "sun8i_r40_ccu", - .id = UCLASS_CLK, - .of_match = r40_clk_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = r40_clk_bind, + .num_gates = ARRAY_SIZE(r40_gates), + .num_resets = ARRAY_SIZE(r40_resets), }; diff --git a/drivers/clk/sunxi/clk_sunxi.c b/drivers/clk/sunxi/clk_sunxi.c index 9a21367a5d0..ec02a2d0370 100644 --- a/drivers/clk/sunxi/clk_sunxi.c +++ b/drivers/clk/sunxi/clk_sunxi.c @@ -12,25 +12,31 @@ #include <reset.h> #include <asm/io.h> #include <clk/sunxi.h> +#include <dm/device-internal.h> #include <linux/bitops.h> #include <linux/log2.h> -static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv, +extern U_BOOT_DRIVER(sunxi_reset); + +static const struct ccu_clk_gate *plat_to_gate(struct ccu_plat *plat, unsigned long id) { - return &priv->desc->gates[id]; + if (id >= plat->desc->num_gates) + return NULL; + + return &plat->desc->gates[id]; } static int sunxi_set_gate(struct clk *clk, bool on) { - struct ccu_priv *priv = dev_get_priv(clk->dev); - const struct ccu_clk_gate *gate = priv_to_gate(priv, clk->id); + struct ccu_plat *plat = dev_get_plat(clk->dev); + const struct ccu_clk_gate *gate = plat_to_gate(plat, clk->id); u32 reg; - if ((gate->flags & CCU_CLK_F_DUMMY_GATE)) + if (gate && (gate->flags & CCU_CLK_F_DUMMY_GATE)) return 0; - if (!(gate->flags & CCU_CLK_F_IS_VALID)) { + if (!gate || !(gate->flags & CCU_CLK_F_IS_VALID)) { printf("%s: (CLK#%ld) unhandled\n", __func__, clk->id); return 0; } @@ -38,13 +44,13 @@ static int sunxi_set_gate(struct clk *clk, bool on) debug("%s: (CLK#%ld) off#0x%x, BIT(%d)\n", __func__, clk->id, gate->off, ilog2(gate->bit)); - reg = readl(priv->base + gate->off); + reg = readl(plat->base + gate->off); if (on) reg |= gate->bit; else reg &= ~gate->bit; - writel(reg, priv->base + gate->off); + writel(reg, plat->base + gate->off); return 0; } @@ -64,21 +70,19 @@ struct clk_ops sunxi_clk_ops = { .disable = sunxi_clk_disable, }; -int sunxi_clk_probe(struct udevice *dev) +static int sunxi_clk_bind(struct udevice *dev) +{ + /* Reuse the platform data for the reset driver. */ + return device_bind(dev, DM_DRIVER_REF(sunxi_reset), "reset", + dev_get_plat(dev), dev_ofnode(dev), NULL); +} + +static int sunxi_clk_probe(struct udevice *dev) { - struct ccu_priv *priv = dev_get_priv(dev); struct clk_bulk clk_bulk; struct reset_ctl_bulk rst_bulk; int ret; - priv->base = dev_read_addr_ptr(dev); - if (!priv->base) - return -ENOMEM; - - priv->desc = (const struct ccu_desc *)dev_get_driver_data(dev); - if (!priv->desc) - return -EINVAL; - ret = clk_get_bulk(dev, &clk_bulk); if (!ret) clk_enable_bulk(&clk_bulk); @@ -89,3 +93,138 @@ int sunxi_clk_probe(struct udevice *dev) return 0; } + +static int sunxi_clk_of_to_plat(struct udevice *dev) +{ + struct ccu_plat *plat = dev_get_plat(dev); + + plat->base = dev_read_addr_ptr(dev); + if (!plat->base) + return -ENOMEM; + + plat->desc = (const struct ccu_desc *)dev_get_driver_data(dev); + if (!plat->desc) + return -EINVAL; + + return 0; +} + +extern const struct ccu_desc a10_ccu_desc; +extern const struct ccu_desc a10s_ccu_desc; +extern const struct ccu_desc a23_ccu_desc; +extern const struct ccu_desc a31_ccu_desc; +extern const struct ccu_desc a31_r_ccu_desc; +extern const struct ccu_desc a64_ccu_desc; +extern const struct ccu_desc a80_ccu_desc; +extern const struct ccu_desc a80_mmc_clk_desc; +extern const struct ccu_desc a83t_ccu_desc; +extern const struct ccu_desc f1c100s_ccu_desc; +extern const struct ccu_desc h3_ccu_desc; +extern const struct ccu_desc h6_ccu_desc; +extern const struct ccu_desc h616_ccu_desc; +extern const struct ccu_desc h6_r_ccu_desc; +extern const struct ccu_desc r40_ccu_desc; +extern const struct ccu_desc v3s_ccu_desc; + +static const struct udevice_id sunxi_clk_ids[] = { +#ifdef CONFIG_CLK_SUN4I_A10 + { .compatible = "allwinner,sun4i-a10-ccu", + .data = (ulong)&a10_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN5I_A10S + { .compatible = "allwinner,sun5i-a10s-ccu", + .data = (ulong)&a10s_ccu_desc }, + { .compatible = "allwinner,sun5i-a13-ccu", + .data = (ulong)&a10s_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN6I_A31 + { .compatible = "allwinner,sun6i-a31-ccu", + .data = (ulong)&a31_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN4I_A10 + { .compatible = "allwinner,sun7i-a20-ccu", + .data = (ulong)&a10_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN8I_A23 + { .compatible = "allwinner,sun8i-a23-ccu", + .data = (ulong)&a23_ccu_desc }, + { .compatible = "allwinner,sun8i-a33-ccu", + .data = (ulong)&a23_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN8I_A83T + { .compatible = "allwinner,sun8i-a83t-ccu", + .data = (ulong)&a83t_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN6I_A31_R + { .compatible = "allwinner,sun8i-a83t-r-ccu", + .data = (ulong)&a31_r_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN8I_H3 + { .compatible = "allwinner,sun8i-h3-ccu", + .data = (ulong)&h3_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN6I_A31_R + { .compatible = "allwinner,sun8i-h3-r-ccu", + .data = (ulong)&a31_r_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN8I_R40 + { .compatible = "allwinner,sun8i-r40-ccu", + .data = (ulong)&r40_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN8I_V3S + { .compatible = "allwinner,sun8i-v3-ccu", + .data = (ulong)&v3s_ccu_desc }, + { .compatible = "allwinner,sun8i-v3s-ccu", + .data = (ulong)&v3s_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN9I_A80 + { .compatible = "allwinner,sun9i-a80-ccu", + .data = (ulong)&a80_ccu_desc }, + { .compatible = "allwinner,sun9i-a80-mmc-config-clk", + .data = (ulong)&a80_mmc_clk_desc }, +#endif +#ifdef CONFIG_CLK_SUN50I_A64 + { .compatible = "allwinner,sun50i-a64-ccu", + .data = (ulong)&a64_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN6I_A31_R + { .compatible = "allwinner,sun50i-a64-r-ccu", + .data = (ulong)&a31_r_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN8I_H3 + { .compatible = "allwinner,sun50i-h5-ccu", + .data = (ulong)&h3_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN50I_H6 + { .compatible = "allwinner,sun50i-h6-ccu", + .data = (ulong)&h6_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN50I_H6_R + { .compatible = "allwinner,sun50i-h6-r-ccu", + .data = (ulong)&h6_r_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN50I_H616 + { .compatible = "allwinner,sun50i-h616-ccu", + .data = (ulong)&h616_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN50I_H6_R + { .compatible = "allwinner,sun50i-h616-r-ccu", + .data = (ulong)&h6_r_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUNIV_F1C100S + { .compatible = "allwinner,suniv-f1c100s-ccu", + .data = (ulong)&f1c100s_ccu_desc }, +#endif + { } +}; + +U_BOOT_DRIVER(sunxi_clk) = { + .name = "sunxi_clk", + .id = UCLASS_CLK, + .of_match = sunxi_clk_ids, + .bind = sunxi_clk_bind, + .probe = sunxi_clk_probe, + .of_to_plat = sunxi_clk_of_to_plat, + .plat_auto = sizeof(struct ccu_plat), + .ops = &sunxi_clk_ops, +}; diff --git a/drivers/clk/sunxi/clk_v3s.c b/drivers/clk/sunxi/clk_v3s.c index 67d215cbba8..f2fd11eac2c 100644 --- a/drivers/clk/sunxi/clk_v3s.c +++ b/drivers/clk/sunxi/clk_v3s.c @@ -49,30 +49,9 @@ static struct ccu_reset v3s_resets[] = { [RST_BUS_UART2] = RESET(0x2d8, BIT(18)), }; -static const struct ccu_desc v3s_ccu_desc = { +const struct ccu_desc v3s_ccu_desc = { .gates = v3s_gates, .resets = v3s_resets, -}; - -static int v3s_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(v3s_resets)); -} - -static const struct udevice_id v3s_clk_ids[] = { - { .compatible = "allwinner,sun8i-v3s-ccu", - .data = (ulong)&v3s_ccu_desc }, - { .compatible = "allwinner,sun8i-v3-ccu", - .data = (ulong)&v3s_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun8i_v3s) = { - .name = "sun8i_v3s_ccu", - .id = UCLASS_CLK, - .of_match = v3s_clk_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = v3s_clk_bind, + .num_gates = ARRAY_SIZE(v3s_gates), + .num_resets = ARRAY_SIZE(v3s_resets), }; diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c index a29a76c58d3..6de0b0a3554 100644 --- a/drivers/mtd/nand/raw/sunxi_nand_spl.c +++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c @@ -208,7 +208,7 @@ static void nand_apply_config(const struct nfc_config *conf) val = readl(SUNXI_NFC_BASE + NFC_CTL); val &= ~NFC_CTL_PAGE_SIZE_MASK; - writel(val | NFC_CTL_RAM_METHOD | NFC_CTL_PAGE_SIZE(conf->page_size), + writel(val | NFC_CTL_PAGE_SIZE(conf->page_size), SUNXI_NFC_BASE + NFC_CTL); writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_CNT); writel(conf->page_size, SUNXI_NFC_BASE + NFC_SPARE_AREA); diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig index f83876c5761..096338f27bf 100644 --- a/drivers/mtd/spi/Kconfig +++ b/drivers/mtd/spi/Kconfig @@ -97,6 +97,13 @@ config SPI_FLASH_SMART_HWCAPS can support a type of operation in a much more refined way compared to using flags like SPI_RX_DUAL, SPI_TX_QUAD, etc. +config SPI_NOR_BOOT_SOFT_RESET_EXT_INVERT + bool "Command extension type is INVERT for Software Reset on boot" + default n + help + Because of SFDP information can not be get before boot. + So define command extension type is INVERT when Software Reset on boot only. + config SPI_FLASH_SOFT_RESET bool "Software Reset support for SPI NOR flashes" help diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 3b7c817c023..8a226a7af55 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -65,6 +65,10 @@ struct sfdp_parameter_header { #define SFDP_SECTOR_MAP_ID 0xff81 /* Sector Map Table */ #define SFDP_SST_ID 0x01bf /* Manufacturer specific Table */ #define SFDP_PROFILE1_ID 0xff05 /* xSPI Profile 1.0 Table */ +#define SFDP_SCCR_MAP_ID 0xff87 /* + * Status, Control and Configuration + * Register Map. + */ #define SFDP_SIGNATURE 0x50444653U #define SFDP_JESD216_MAJOR 1 @@ -174,6 +178,9 @@ struct sfdp_header { #define PROFILE1_DWORD5_DUMMY_100MHZ GENMASK(11, 7) #define PROFILE1_DUMMY_DEFAULT 20 +/* Status, Control and Configuration Register Map(SCCR) */ +#define SCCR_DWORD22_OCTAL_DTR_EN_VOLATILE BIT(31) + struct sfdp_bfpt { u32 dwords[BFPT_DWORD_MAX]; }; @@ -1308,13 +1315,13 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) } /* - * Check if a region of the flash is (completely) locked. See stm_lock() for + * Check if a region of the flash is (completely) unlocked. See stm_lock() for * more info. * - * Returns 1 if entire region is locked, 0 if any portion is unlocked, and + * Returns 1 if entire region is unlocked, 0 if any portion is locked, and * negative on errors. */ -static int stm_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len) +static int stm_is_unlocked(struct spi_nor *nor, loff_t ofs, uint64_t len) { int status; @@ -1322,7 +1329,7 @@ static int stm_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len) if (status < 0) return status; - return stm_is_locked_sr(nor, ofs, len, status); + return stm_is_unlocked_sr(nor, ofs, len, status); } #endif /* CONFIG_SPI_FLASH_STMICRO */ @@ -1555,16 +1562,16 @@ static int sst26_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) } /* - * Returns EACCES (positive value) if region is locked, 0 if region is unlocked, - * and negative on errors. + * Returns EACCES (positive value) if region is (partially) locked, 0 if region + * is completely unlocked, and negative on errors. */ -static int sst26_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len) +static int sst26_is_unlocked(struct spi_nor *nor, loff_t ofs, uint64_t len) { /* - * is_locked function is used for check before reading or erasing flash - * region, so offset and length might be not 64k allighned, so adjust - * them to be 64k allighned as sst26_lock_ctl works only with 64k - * allighned regions. + * is_unlocked function is used for check before reading or erasing + * flash region, so offset and length might be not 64k aligned, so + * adjust them to be 64k aligned as sst26_lock_ctl works only with 64k + * aligned regions. */ ofs -= ofs & (SZ_64K - 1); len = len & (SZ_64K - 1) ? (len & ~(SZ_64K - 1)) + SZ_64K : len; @@ -2457,6 +2464,44 @@ out: } /** + * spi_nor_parse_sccr() - Parse the Status, Control and Configuration Register + * Map. + * @nor: pointer to a 'struct spi_nor' + * @sccr_header: pointer to the 'struct sfdp_parameter_header' describing + * the SCCR Map table length and version. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_nor_parse_sccr(struct spi_nor *nor, + const struct sfdp_parameter_header *sccr_header) +{ + u32 *table, addr; + size_t len; + int ret, i; + + len = sccr_header->length * sizeof(*table); + table = kmalloc(len, GFP_KERNEL); + if (!table) + return -ENOMEM; + + addr = SFDP_PARAM_HEADER_PTP(sccr_header); + ret = spi_nor_read_sfdp(nor, addr, len, table); + if (ret) + goto out; + + /* Fix endianness of the table DWORDs. */ + for (i = 0; i < sccr_header->length; i++) + table[i] = le32_to_cpu(table[i]); + + if (FIELD_GET(SCCR_DWORD22_OCTAL_DTR_EN_VOLATILE, table[22])) + nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE; + +out: + kfree(table); + return ret; +} + +/** * spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters. * @nor: pointer to a 'struct spi_nor' * @params: pointer to the 'struct spi_nor_flash_parameter' to be @@ -2562,6 +2607,10 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor, err = spi_nor_parse_profile1(nor, param_header, params); break; + case SFDP_SCCR_MAP_ID: + err = spi_nor_parse_sccr(nor, param_header); + break; + default: break; } @@ -3526,6 +3575,84 @@ static struct spi_nor_fixups mt35xu512aba_fixups = { }; #endif /* CONFIG_SPI_FLASH_MT35XU */ +#if CONFIG_IS_ENABLED(SPI_FLASH_MACRONIX) +/** + * spi_nor_macronix_octal_dtr_enable() - Enable octal DTR on Macronix flashes. + * @nor: pointer to a 'struct spi_nor' + * + * Set Macronix max dummy cycles 20 to allow the flash to run at fastest frequency. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_nor_macronix_octal_dtr_enable(struct spi_nor *nor) +{ + struct spi_mem_op op; + int ret; + u8 buf; + + ret = write_enable(nor); + if (ret) + return ret; + + buf = SPINOR_REG_MXIC_DC_20; + op = (struct spi_mem_op) + SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_CR2, 1), + SPI_MEM_OP_ADDR(4, SPINOR_REG_MXIC_CR2_DC, 1), + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_OUT(1, &buf, 1)); + + ret = spi_mem_exec_op(nor->spi, &op); + if (ret) + return ret; + + ret = spi_nor_wait_till_ready(nor); + if (ret) + return ret; + + nor->read_dummy = MXIC_MAX_DC; + ret = write_enable(nor); + if (ret) + return ret; + + buf = SPINOR_REG_MXIC_OPI_DTR_EN; + op = (struct spi_mem_op) + SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_CR2, 1), + SPI_MEM_OP_ADDR(4, SPINOR_REG_MXIC_CR2_MODE, 1), + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_OUT(1, &buf, 1)); + + ret = spi_mem_exec_op(nor->spi, &op); + if (ret) { + dev_err(nor->dev, "Failed to enable octal DTR mode\n"); + return ret; + } + nor->reg_proto = SNOR_PROTO_8_8_8_DTR; + + return 0; +} + +static void macronix_octal_default_init(struct spi_nor *nor) +{ + nor->octal_dtr_enable = spi_nor_macronix_octal_dtr_enable; +} + +static void macronix_octal_post_sfdp_fixup(struct spi_nor *nor, + struct spi_nor_flash_parameter *params) +{ + /* + * Adding SNOR_HWCAPS_PP_8_8_8_DTR in hwcaps.mask when + * SPI_NOR_OCTAL_DTR_READ flag exists. + */ + if (params->hwcaps.mask & SNOR_HWCAPS_READ_8_8_8_DTR) + params->hwcaps.mask |= SNOR_HWCAPS_PP_8_8_8_DTR; +} + +static struct spi_nor_fixups macronix_octal_fixups = { + .default_init = macronix_octal_default_init, + .post_sfdp = macronix_octal_post_sfdp_fixup, +}; +#endif /* CONFIG_SPI_FLASH_MACRONIX */ + /** spi_nor_octal_dtr_enable() - enable Octal DTR I/O if needed * @nor: pointer to a 'struct spi_nor' * @@ -3542,6 +3669,9 @@ static int spi_nor_octal_dtr_enable(struct spi_nor *nor) nor->write_proto == SNOR_PROTO_8_8_8_DTR)) return 0; + if (!(nor->flags & SNOR_F_IO_MODE_EN_VOLATILE)) + return 0; + ret = nor->octal_dtr_enable(nor); if (ret) return ret; @@ -3619,7 +3749,12 @@ static int spi_nor_soft_reset(struct spi_nor *nor) enum spi_nor_cmd_ext ext; ext = nor->cmd_ext_type; - nor->cmd_ext_type = SPI_NOR_EXT_REPEAT; + if (nor->cmd_ext_type == SPI_NOR_EXT_NONE) { + nor->cmd_ext_type = SPI_NOR_EXT_REPEAT; +#if CONFIG_IS_ENABLED(SPI_NOR_BOOT_SOFT_RESET_EXT_INVERT) + nor->cmd_ext_type = SPI_NOR_EXT_INVERT; +#endif /* SPI_NOR_BOOT_SOFT_RESET_EXT_INVERT */ + } op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_SRSTEN, 0), SPI_MEM_OP_NO_DUMMY, @@ -3696,6 +3831,10 @@ void spi_nor_set_fixups(struct spi_nor *nor) if (!strcmp(nor->info->name, "mt35xu512aba")) nor->fixups = &mt35xu512aba_fixups; #endif + +#if CONFIG_IS_ENABLED(SPI_FLASH_MACRONIX) + nor->fixups = ¯onix_octal_fixups; +#endif /* SPI_FLASH_MACRONIX */ } int spi_nor_scan(struct spi_nor *nor) @@ -3785,7 +3924,7 @@ int spi_nor_scan(struct spi_nor *nor) info->flags & SPI_NOR_HAS_LOCK) { nor->flash_lock = stm_lock; nor->flash_unlock = stm_unlock; - nor->flash_is_locked = stm_is_locked; + nor->flash_is_unlocked = stm_is_unlocked; } #endif @@ -3797,7 +3936,7 @@ int spi_nor_scan(struct spi_nor *nor) if (info->flags & SPI_NOR_HAS_SST26LOCK) { nor->flash_lock = sst26_lock; nor->flash_unlock = sst26_unlock; - nor->flash_is_locked = sst26_is_locked; + nor->flash_is_unlocked = sst26_is_unlocked; } #endif diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c index 67278c40e35..4fe8b0d92c4 100644 --- a/drivers/mtd/spi/spi-nor-ids.c +++ b/drivers/mtd/spi/spi-nor-ids.c @@ -198,7 +198,24 @@ const struct flash_info spi_nor_ids[] = { { INFO("mx66l2g45g", 0xc2201c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { INFO("mx25l1633e", 0xc22415, 0, 64 * 1024, 32, SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES | SECT_4K) }, { INFO("mx25r6435f", 0xc22817, 0, 64 * 1024, 128, SECT_4K) }, - { INFO("mx66uw2g345g", 0xc2943c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx66uw2g345gx0", 0xc2943c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx66lm1g45g", 0xc2853b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx25lm51245g", 0xc2853a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx25lw51245g", 0xc2863a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx25lm25645g", 0xc28539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx66uw2g345g", 0xc2843c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx66um1g45g", 0xc2803b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx66uw1g45g", 0xc2813b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx25uw51245g", 0xc2813a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx25uw51345g", 0xc2843a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx25um25645g", 0xc28039, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx25uw25645g", 0xc28139, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx25um25345g", 0xc28339, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx25uw25345g", 0xc28439, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx25uw12845g", 0xc28138, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx25uw12345g", 0xc28438, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx25uw6445g", 0xc28137, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx25uw6345g", 0xc28437, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, #endif #ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */ @@ -398,6 +415,16 @@ const struct flash_info spi_nor_ids[] = { SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { + INFO("w25q512nwq", 0xef6020, 0, 64 * 1024, 1024, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { + INFO("w25q512nwm", 0xef8020, 0, 64 * 1024, 1024, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { INFO("w25q01jv", 0xef4021, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c index 2220f84b697..9cca8fa4e0a 100644 --- a/drivers/net/sun8i_emac.c +++ b/drivers/net/sun8i_emac.c @@ -16,7 +16,6 @@ #include <asm/global_data.h> #include <asm/gpio.h> #include <asm/io.h> -#include <asm/arch/clock.h> #include <common.h> #include <clk.h> #include <dm.h> @@ -857,7 +856,7 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev) priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1); pdata->phy_interface = dev_read_phy_mode(dev); - printf("phy interface%d\n", pdata->phy_interface); + debug("phy interface %d\n", pdata->phy_interface); if (pdata->phy_interface == PHY_INTERFACE_MODE_NA) return -EINVAL; diff --git a/drivers/phy/allwinner/Kconfig b/drivers/phy/allwinner/Kconfig index d3ff82f73a0..f8f1e99c4f5 100644 --- a/drivers/phy/allwinner/Kconfig +++ b/drivers/phy/allwinner/Kconfig @@ -13,6 +13,16 @@ config PHY_SUN4I_USB This driver controls the entire USB PHY block, both the USB OTG parts, as well as the 2 regular USB 2 host PHYs. +config INITIAL_USB_SCAN_DELAY + int "Delay initial USB scan by x ms to allow builtin devices to init" + depends on PHY_SUN4I_USB + default 0 + help + Some boards have on board usb devices which need longer than + the USB spec's 1 second to connect from board powerup. Set + this option to a nonzero value to add an extra delay before + the first USB bus scan. + config PHY_SUN50I_USB3 bool "Allwinner sun50i USB3 PHY driver" depends on ARCH_SUNXI diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index aef2cb8f6f8..2e969ab91e3 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -20,8 +20,6 @@ #include <reset.h> #include <asm/gpio.h> #include <asm/io.h> -#include <asm/arch/clock.h> -#include <asm/arch/cpu.h> #include <dm/device_compat.h> #include <linux/bitops.h> #include <linux/delay.h> @@ -34,7 +32,8 @@ #define REG_PHYTUNE 0x0c #define REG_PHYCTL_A33 0x10 #define REG_PHY_OTGCTL 0x20 -#define REG_PMU_UNK1 0x10 + +#define REG_HCI_PHY_CTL 0x10 /* Common Control Bits for Both PHYs */ #define PHY_PLL_BW 0x03 @@ -65,6 +64,7 @@ /* A83T specific control bits for PHY0 */ #define PHY_CTL_VBUSVLDEXT BIT(5) #define PHY_CTL_SIDDQ BIT(3) +#define PHY_CTL_H3_SIDDQ BIT(1) /* A83T specific control bits for PHY2 HSIC */ #define SUNXI_EHCI_HS_FORCE BIT(20) @@ -89,9 +89,9 @@ struct sun4i_usb_phy_cfg { int num_phys; enum sun4i_usb_phy_type type; u32 disc_thresh; + u32 hci_phy_ctl_clear; u8 phyctl_offset; bool dedicated_clocks; - bool enable_pmu_unk1; bool phy0_dual_route; int missing_phys; }; @@ -277,6 +277,12 @@ static int sun4i_usb_phy_init(struct phy *phy) return ret; } + if (usb_phy->pmu && data->cfg->hci_phy_ctl_clear) { + val = readl(usb_phy->pmu + REG_HCI_PHY_CTL); + val &= ~data->cfg->hci_phy_ctl_clear; + writel(val, usb_phy->pmu + REG_HCI_PHY_CTL); + } + if (data->cfg->type == sun8i_a83t_phy || data->cfg->type == sun50i_h6_phy) { if (phy->id == 0) { @@ -286,11 +292,6 @@ static int sun4i_usb_phy_init(struct phy *phy) writel(val, data->base + data->cfg->phyctl_offset); } } else { - if (usb_phy->pmu && data->cfg->enable_pmu_unk1) { - val = readl(usb_phy->pmu + REG_PMU_UNK1); - writel(val & ~2, usb_phy->pmu + REG_PMU_UNK1); - } - if (usb_phy->id == 0) sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, PHY_RES45_CAL_DATA, @@ -530,7 +531,6 @@ static const struct sun4i_usb_phy_cfg sun4i_a10_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A10, .dedicated_clocks = false, - .enable_pmu_unk1 = false, }; static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = { @@ -539,7 +539,6 @@ static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = { .disc_thresh = 2, .phyctl_offset = REG_PHYCTL_A10, .dedicated_clocks = false, - .enable_pmu_unk1 = false, }; static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = { @@ -548,7 +547,6 @@ static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A10, .dedicated_clocks = true, - .enable_pmu_unk1 = false, }; static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = { @@ -557,7 +555,6 @@ static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = { .disc_thresh = 2, .phyctl_offset = REG_PHYCTL_A10, .dedicated_clocks = false, - .enable_pmu_unk1 = false, }; static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = { @@ -566,7 +563,6 @@ static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A10, .dedicated_clocks = true, - .enable_pmu_unk1 = false, }; static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = { @@ -575,7 +571,6 @@ static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, .dedicated_clocks = true, - .enable_pmu_unk1 = false, }; static const struct sun4i_usb_phy_cfg sun8i_a83t_cfg = { @@ -591,7 +586,7 @@ static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, .dedicated_clocks = true, - .enable_pmu_unk1 = true, + .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ, .phy0_dual_route = true, }; @@ -601,7 +596,7 @@ static const struct sun4i_usb_phy_cfg sun8i_r40_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, .dedicated_clocks = true, - .enable_pmu_unk1 = true, + .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ, .phy0_dual_route = true, }; @@ -611,7 +606,16 @@ static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, .dedicated_clocks = true, - .enable_pmu_unk1 = true, + .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ, + .phy0_dual_route = true, +}; + +static const struct sun4i_usb_phy_cfg sun20i_d1_cfg = { + .num_phys = 2, + .type = sun50i_h6_phy, + .phyctl_offset = REG_PHYCTL_A33, + .dedicated_clocks = true, + .hci_phy_ctl_clear = PHY_CTL_SIDDQ, .phy0_dual_route = true, }; @@ -621,7 +625,7 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, .dedicated_clocks = true, - .enable_pmu_unk1 = true, + .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ, .phy0_dual_route = true, }; @@ -631,7 +635,6 @@ static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, .dedicated_clocks = true, - .enable_pmu_unk1 = true, .phy0_dual_route = true, .missing_phys = BIT(1) | BIT(2), }; @@ -647,6 +650,7 @@ static const struct udevice_id sun4i_usb_phy_ids[] = { { .compatible = "allwinner,sun8i-h3-usb-phy", .data = (ulong)&sun8i_h3_cfg }, { .compatible = "allwinner,sun8i-r40-usb-phy", .data = (ulong)&sun8i_r40_cfg }, { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = (ulong)&sun8i_v3s_cfg }, + { .compatible = "allwinner,sun20i-d1-usb-phy", .data = (ulong)&sun20i_d1_cfg }, { .compatible = "allwinner,sun50i-a64-usb-phy", .data = (ulong)&sun50i_a64_cfg}, { .compatible = "allwinner,sun50i-h6-usb-phy", .data = (ulong)&sun50i_h6_cfg}, { } diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c index e2a9c2a142b..e484d1fff44 100644 --- a/drivers/reset/reset-sunxi.c +++ b/drivers/reset/reset-sunxi.c @@ -12,30 +12,22 @@ #include <reset-uclass.h> #include <asm/io.h> #include <clk/sunxi.h> -#include <dm/device-internal.h> -#include <dm/lists.h> #include <linux/bitops.h> #include <linux/log2.h> -struct sunxi_reset_priv { - void *base; - ulong count; - const struct ccu_desc *desc; -}; - -static const struct ccu_reset *priv_to_reset(struct sunxi_reset_priv *priv, +static const struct ccu_reset *plat_to_reset(struct ccu_plat *plat, unsigned long id) { - return &priv->desc->resets[id]; + return &plat->desc->resets[id]; } static int sunxi_reset_request(struct reset_ctl *reset_ctl) { - struct sunxi_reset_priv *priv = dev_get_priv(reset_ctl->dev); + struct ccu_plat *plat = dev_get_plat(reset_ctl->dev); debug("%s: (RST#%ld)\n", __func__, reset_ctl->id); - if (reset_ctl->id >= priv->count) + if (reset_ctl->id >= plat->desc->num_resets) return -EINVAL; return 0; @@ -43,8 +35,8 @@ static int sunxi_reset_request(struct reset_ctl *reset_ctl) static int sunxi_set_reset(struct reset_ctl *reset_ctl, bool on) { - struct sunxi_reset_priv *priv = dev_get_priv(reset_ctl->dev); - const struct ccu_reset *reset = priv_to_reset(priv, reset_ctl->id); + struct ccu_plat *plat = dev_get_plat(reset_ctl->dev); + const struct ccu_reset *reset = plat_to_reset(plat, reset_ctl->id); u32 reg; if (!(reset->flags & CCU_RST_F_IS_VALID)) { @@ -55,13 +47,13 @@ static int sunxi_set_reset(struct reset_ctl *reset_ctl, bool on) debug("%s: (RST#%ld) off#0x%x, BIT(%d)\n", __func__, reset_ctl->id, reset->off, ilog2(reset->bit)); - reg = readl(priv->base + reset->off); + reg = readl(plat->base + reset->off); if (on) reg |= reset->bit; else reg &= ~reset->bit; - writel(reg, priv->base + reset->off); + writel(reg, plat->base + reset->off); return 0; } @@ -82,39 +74,8 @@ struct reset_ops sunxi_reset_ops = { .rst_deassert = sunxi_reset_deassert, }; -static int sunxi_reset_probe(struct udevice *dev) -{ - struct sunxi_reset_priv *priv = dev_get_priv(dev); - - priv->base = dev_read_addr_ptr(dev); - - return 0; -} - -int sunxi_reset_bind(struct udevice *dev, ulong count) -{ - struct udevice *rst_dev; - struct sunxi_reset_priv *priv; - int ret; - - ret = device_bind_driver_to_node(dev, "sunxi_reset", "reset", - dev_ofnode(dev), &rst_dev); - if (ret) { - debug("failed to bind sunxi_reset driver (ret=%d)\n", ret); - return ret; - } - priv = malloc(sizeof(struct sunxi_reset_priv)); - priv->count = count; - priv->desc = (const struct ccu_desc *)dev_get_driver_data(dev); - dev_set_priv(rst_dev, priv); - - return 0; -} - U_BOOT_DRIVER(sunxi_reset) = { .name = "sunxi_reset", .id = UCLASS_RESET, .ops = &sunxi_reset_ops, - .probe = sunxi_reset_probe, - .priv_auto = sizeof(struct sunxi_reset_priv), }; diff --git a/drivers/spi/spi-sunxi.c b/drivers/spi/spi-sunxi.c index b6cd7ddafad..c56d82d998a 100644 --- a/drivers/spi/spi-sunxi.c +++ b/drivers/spi/spi-sunxi.c @@ -72,10 +72,18 @@ DECLARE_GLOBAL_DATA_PTR; #define SUN4I_XMIT_CNT(cnt) ((cnt) & SUN4I_MAX_XFER_SIZE) #define SUN4I_FIFO_STA_RF_CNT_BITS 0 -#define SUN4I_SPI_MAX_RATE 24000000 +#ifdef CONFIG_MACH_SUNIV +/* the AHB clock, which we programmed to be 1/3 of PLL_PERIPH@600MHz */ +#define SUNXI_INPUT_CLOCK 200000000 /* 200 MHz */ +#define SUN4I_SPI_MAX_RATE (SUNXI_INPUT_CLOCK / 2) +#else +/* the SPI mod clock, defaulting to be 1/1 of the HOSC@24MHz */ +#define SUNXI_INPUT_CLOCK 24000000 /* 24 MHz */ +#define SUN4I_SPI_MAX_RATE SUNXI_INPUT_CLOCK +#endif #define SUN4I_SPI_MIN_RATE 3000 #define SUN4I_SPI_DEFAULT_RATE 1000000 -#define SUN4I_SPI_TIMEOUT_US 1000000 +#define SUN4I_SPI_TIMEOUT_MS 1000 #define SPI_REG(priv, reg) ((priv)->base + \ (priv)->variant->regs[reg]) @@ -221,6 +229,60 @@ err_ahb: return ret; } +static void sun4i_spi_set_speed_mode(struct udevice *dev) +{ + struct sun4i_spi_priv *priv = dev_get_priv(dev); + unsigned int div; + u32 reg; + + /* + * Setup clock divider. + * + * We have two choices there. Either we can use the clock + * divide rate 1, which is calculated thanks to this formula: + * SPI_CLK = MOD_CLK / (2 ^ (cdr + 1)) + * Or we can use CDR2, which is calculated with the formula: + * SPI_CLK = MOD_CLK / (2 * (cdr + 1)) + * Whether we use the former or the latter is set through the + * DRS bit. + * + * First try CDR2, and if we can't reach the expected + * frequency, fall back to CDR1. + */ + + div = DIV_ROUND_UP(SUNXI_INPUT_CLOCK, priv->freq); + reg = readl(SPI_REG(priv, SPI_CCR)); + + if ((div / 2) <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) { + div /= 2; + if (div > 0) + div--; + + reg &= ~(SUN4I_CLK_CTL_CDR2_MASK | SUN4I_CLK_CTL_DRS); + reg |= SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS; + } else { + div = fls(div - 1); + /* The F1C100s encodes the divider as 2^(n+1) */ + if (IS_ENABLED(CONFIG_MACH_SUNIV)) + div--; + reg &= ~((SUN4I_CLK_CTL_CDR1_MASK << 8) | SUN4I_CLK_CTL_DRS); + reg |= SUN4I_CLK_CTL_CDR1(div); + } + + writel(reg, SPI_REG(priv, SPI_CCR)); + + reg = readl(SPI_REG(priv, SPI_TCR)); + reg &= ~(SPI_BIT(priv, SPI_TCR_CPOL) | SPI_BIT(priv, SPI_TCR_CPHA)); + + if (priv->mode & SPI_CPOL) + reg |= SPI_BIT(priv, SPI_TCR_CPOL); + + if (priv->mode & SPI_CPHA) + reg |= SPI_BIT(priv, SPI_TCR_CPHA); + + writel(reg, SPI_REG(priv, SPI_TCR)); +} + static int sun4i_spi_claim_bus(struct udevice *dev) { struct sun4i_spi_priv *priv = dev_get_priv(dev->parent); @@ -240,6 +302,8 @@ static int sun4i_spi_claim_bus(struct udevice *dev) setbits_le32(SPI_REG(priv, SPI_TCR), SPI_BIT(priv, SPI_TCR_CS_MANUAL) | SPI_BIT(priv, SPI_TCR_CS_ACTIVE_LOW)); + sun4i_spi_set_speed_mode(dev->parent); + return 0; } @@ -262,7 +326,6 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen, struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); u32 len = bitlen / 8; - u32 rx_fifocnt; u8 nbytes; int ret; @@ -300,13 +363,10 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen, setbits_le32(SPI_REG(priv, SPI_TCR), SPI_BIT(priv, SPI_TCR_XCH)); - /* Wait till RX FIFO to be empty */ - ret = readl_poll_timeout(SPI_REG(priv, SPI_FSR), - rx_fifocnt, - (((rx_fifocnt & - SPI_BIT(priv, SPI_FSR_RF_CNT_MASK)) >> - SUN4I_FIFO_STA_RF_CNT_BITS) >= nbytes), - SUN4I_SPI_TIMEOUT_US); + /* Wait for the transfer to be done */ + ret = wait_for_bit_le32((const void *)SPI_REG(priv, SPI_TCR), + SPI_BIT(priv, SPI_TCR_XCH), + false, SUN4I_SPI_TIMEOUT_MS, false); if (ret < 0) { printf("ERROR: sun4i_spi: Timeout transferring data\n"); sun4i_spi_set_cs(bus, slave_plat->cs, false); @@ -329,46 +389,14 @@ static int sun4i_spi_set_speed(struct udevice *dev, uint speed) { struct sun4i_spi_plat *plat = dev_get_plat(dev); struct sun4i_spi_priv *priv = dev_get_priv(dev); - unsigned int div; - u32 reg; if (speed > plat->max_hz) speed = plat->max_hz; if (speed < SUN4I_SPI_MIN_RATE) speed = SUN4I_SPI_MIN_RATE; - /* - * Setup clock divider. - * - * We have two choices there. Either we can use the clock - * divide rate 1, which is calculated thanks to this formula: - * SPI_CLK = MOD_CLK / (2 ^ (cdr + 1)) - * Or we can use CDR2, which is calculated with the formula: - * SPI_CLK = MOD_CLK / (2 * (cdr + 1)) - * Whether we use the former or the latter is set through the - * DRS bit. - * - * First try CDR2, and if we can't reach the expected - * frequency, fall back to CDR1. - */ - - div = SUN4I_SPI_MAX_RATE / (2 * speed); - reg = readl(SPI_REG(priv, SPI_CCR)); - - if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) { - if (div > 0) - div--; - - reg &= ~(SUN4I_CLK_CTL_CDR2_MASK | SUN4I_CLK_CTL_DRS); - reg |= SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS; - } else { - div = __ilog2(SUN4I_SPI_MAX_RATE) - __ilog2(speed); - reg &= ~((SUN4I_CLK_CTL_CDR1_MASK << 8) | SUN4I_CLK_CTL_DRS); - reg |= SUN4I_CLK_CTL_CDR1(div); - } priv->freq = speed; - writel(reg, SPI_REG(priv, SPI_CCR)); return 0; } @@ -376,19 +404,8 @@ static int sun4i_spi_set_speed(struct udevice *dev, uint speed) static int sun4i_spi_set_mode(struct udevice *dev, uint mode) { struct sun4i_spi_priv *priv = dev_get_priv(dev); - u32 reg; - - reg = readl(SPI_REG(priv, SPI_TCR)); - reg &= ~(SPI_BIT(priv, SPI_TCR_CPOL) | SPI_BIT(priv, SPI_TCR_CPHA)); - - if (mode & SPI_CPOL) - reg |= SPI_BIT(priv, SPI_TCR_CPOL); - - if (mode & SPI_CPHA) - reg |= SPI_BIT(priv, SPI_TCR_CPHA); priv->mode = mode; - writel(reg, SPI_REG(priv, SPI_TCR)); return 0; } diff --git a/include/clk/sunxi.h b/include/clk/sunxi.h index c4a9dee5ebf..c298195c51e 100644 --- a/include/clk/sunxi.h +++ b/include/clk/sunxi.h @@ -70,34 +70,21 @@ struct ccu_reset { struct ccu_desc { const struct ccu_clk_gate *gates; const struct ccu_reset *resets; + u8 num_gates; + u8 num_resets; }; /** - * struct ccu_priv - sunxi clock control unit + * struct ccu_plat - sunxi clock control unit platform data * * @base: base address * @desc: ccu descriptor */ -struct ccu_priv { +struct ccu_plat { void *base; const struct ccu_desc *desc; }; -/** - * sunxi_clk_probe - common sunxi clock probe - * @dev: clock device - */ -int sunxi_clk_probe(struct udevice *dev); - extern struct clk_ops sunxi_clk_ops; -/** - * sunxi_reset_bind() - reset binding - * - * @dev: reset device - * @count: reset count - * Return: 0 success, or error value - */ -int sunxi_reset_bind(struct udevice *dev, ulong count); - #endif /* _CLK_SUNXI_H */ diff --git a/include/configs/sun4i.h b/include/configs/sun4i.h index 0e1baa91bb1..70d451f2243 100644 --- a/include/configs/sun4i.h +++ b/include/configs/sun4i.h @@ -2,18 +2,12 @@ /* * (C) Copyright 2012-2013 Henrik Nordstrom <henrik@henriknordstrom.net> * - * Configuration settings for the Allwinner A10 (sun4i) CPU + * Placeholder wrapper to allow addressing Allwinner A10 (sun4i) CPU + * based devices separately. Please do not add anything in here. */ #ifndef __CONFIG_H #define __CONFIG_H -/* - * A10 specific configuration - */ - -/* - * Include common sunxi configuration where most the settings are - */ #include <configs/sunxi-common.h> #endif /* __CONFIG_H */ diff --git a/include/configs/sun50i.h b/include/configs/sun50i.h index bc2e3a3d008..dfcb321d425 100644 --- a/include/configs/sun50i.h +++ b/include/configs/sun50i.h @@ -1,26 +1,11 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Configuration settings for the Allwinner A64 (sun50i) CPU + * Placeholder wrapper to allow addressing Allwinner A64 (and later) sun50i + * CPU based devices separately. Please do not add anything in here. */ - #ifndef __CONFIG_H #define __CONFIG_H -/* - * A64 specific configuration - */ - -#ifndef CONFIG_SUN50I_GEN_H6 -#define GICD_BASE 0x1c81000 -#define GICC_BASE 0x1c82000 -#else -#define GICD_BASE 0x3021000 -#define GICC_BASE 0x3022000 -#endif - -/* - * Include common sunxi configuration where most the settings are - */ #include <configs/sunxi-common.h> #endif /* __CONFIG_H */ diff --git a/include/configs/sun5i.h b/include/configs/sun5i.h index ada18de7537..30173078548 100644 --- a/include/configs/sun5i.h +++ b/include/configs/sun5i.h @@ -2,18 +2,12 @@ /* * (C) Copyright 2012-2013 Henrik Nordstrom <henrik@henriknordstrom.net> * - * Configuration settings for the Allwinner A13 (sun5i) CPU + * Placeholder wrapper to allow addressing Allwinner A13 (sun5i) CPU + * based devices separately. Please do not add anything in here. */ #ifndef __CONFIG_H #define __CONFIG_H -/* - * High Level Configuration Options - */ - -/* - * Include common sunxi configuration where most the settings are - */ #include <configs/sunxi-common.h> #endif /* __CONFIG_H */ diff --git a/include/configs/sun6i.h b/include/configs/sun6i.h index 0b1fedda108..cbe04ac3c23 100644 --- a/include/configs/sun6i.h +++ b/include/configs/sun6i.h @@ -4,15 +4,12 @@ * (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.net> * (C) Copyright 2013 Maxime Ripard <maxime.ripard@free-electrons.com> * - * Configuration settings for the Allwinner A31 (sun6i) CPU + * Placeholder wrapper to allow addressing Allwinner A31 (sun6i) CPU + * based devices separately. Please do not add anything in here. */ - #ifndef __CONFIG_H #define __CONFIG_H -/* - * Include common sunxi configuration where most the settings are - */ #include <configs/sunxi-common.h> #endif /* __CONFIG_H */ diff --git a/include/configs/sun7i.h b/include/configs/sun7i.h index bc2779fa26f..ad24ab98b52 100644 --- a/include/configs/sun7i.h +++ b/include/configs/sun7i.h @@ -3,14 +3,12 @@ * (C) Copyright 2012-2013 Henrik Nordstrom <henrik@henriknordstrom.net> * (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.net> * - * Configuration settings for the Allwinner A20 (sun7i) CPU + * Placeholder wrapper to allow addressing Allwinner A20 (sun7i) CPU + * based devices separately. Please do not add anything in here. */ #ifndef __CONFIG_H #define __CONFIG_H -/* - * Include common sunxi configuration where most the settings are - */ #include <configs/sunxi-common.h> #endif /* __CONFIG_H */ diff --git a/include/configs/sun8i.h b/include/configs/sun8i.h index 106139d0904..b6cd8d39a8f 100644 --- a/include/configs/sun8i.h +++ b/include/configs/sun8i.h @@ -2,21 +2,12 @@ /* * (C) Copyright 2014 Chen-Yu Tsai <wens@csie.org> * - * Configuration settings for the Allwinner A23 (sun8i) CPU + * Placeholder wrapper to allow addressing Allwinner A23 (and later) sun8i + * CPU based devices separately. Please do not add anything in here. */ - #ifndef __CONFIG_H #define __CONFIG_H -/* - * A23 specific configuration - */ - -#include <asm/arch/cpu.h> - -/* - * Include common sunxi configuration where most the settings are - */ #include <configs/sunxi-common.h> #endif /* __CONFIG_H */ diff --git a/include/configs/sun9i.h b/include/configs/sun9i.h index 6ee08cf0d95..6bf5fc3f66a 100644 --- a/include/configs/sun9i.h +++ b/include/configs/sun9i.h @@ -2,19 +2,12 @@ /* * (C) Copyright 2015 Hans de Goede <hdegoede@redhat.com> * - * Configuration settings for the Allwinner A80 (sun9i) CPU + * Placeholder wrapper to allow addressing Allwinner A80 (sun9i) CPU + * based devices separately. Please do not add anything in here. */ - #ifndef __CONFIG_H #define __CONFIG_H -/* - * A80 specific configuration - */ - -/* - * Include common sunxi configuration where most the settings are - */ #include <configs/sunxi-common.h> #endif /* __CONFIG_H */ diff --git a/include/configs/suniv.h b/include/configs/suniv.h index 6118cd5e1a6..9cc1a77f6c8 100644 --- a/include/configs/suniv.h +++ b/include/configs/suniv.h @@ -1,14 +1,11 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Configuration settings for new Allwinner F-series (suniv) CPU + * Placeholder wrapper to allow addressing Allwinner F-series (suniv) CPU + * based devices separately. Please do not add anything in here. */ - #ifndef __CONFIG_H #define __CONFIG_H -/* - * Include common sunxi configuration where most the settings are - */ #include <configs/sunxi-common.h> #endif /* __CONFIG_H */ diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 4ceeae623de..2595bad9dfe 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -119,6 +119,16 @@ /* Used for Macronix and Winbond flashes. */ #define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */ #define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */ +#define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */ +#define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */ +#define SPINOR_OP_RD_CR2 0x71 /* Read configuration register 2 */ +#define SPINOR_OP_WR_CR2 0x72 /* Write configuration register 2 */ +#define SPINOR_OP_MXIC_DTR_RD 0xee /* Fast Read opcode in DTR mode */ +#define SPINOR_REG_MXIC_CR2_MODE 0x00000000 /* For setting octal DTR mode */ +#define SPINOR_REG_MXIC_OPI_DTR_EN 0x2 /* Enable Octal DTR */ +#define SPINOR_REG_MXIC_CR2_DC 0x00000300 /* For setting dummy cycles */ +#define SPINOR_REG_MXIC_DC_20 0x0 /* Setting dummy cycles to 20 */ +#define MXIC_MAX_DC 20 /* Maximum value of dummy cycles */ /* Used for Spansion flashes only. */ #define SPINOR_OP_BRWR 0x17 /* Bank register write */ @@ -280,6 +290,7 @@ enum spi_nor_option_flags { SNOR_F_USE_CLSR = BIT(5), SNOR_F_BROKEN_RESET = BIT(6), SNOR_F_SOFT_RESET = BIT(7), + SNOR_F_IO_MODE_EN_VOLATILE = BIT(8), }; struct spi_nor; @@ -506,8 +517,8 @@ struct spi_flash { * spi-nor will send the erase opcode via write_reg() * @flash_lock: [FLASH-SPECIFIC] lock a region of the SPI NOR * @flash_unlock: [FLASH-SPECIFIC] unlock a region of the SPI NOR - * @flash_is_locked: [FLASH-SPECIFIC] check if a region of the SPI NOR is - * completely locked + * @flash_is_unlocked: [FLASH-SPECIFIC] check if a region of the SPI NOR is + * completely unlocked * @quad_enable: [FLASH-SPECIFIC] enables SPI NOR quad mode * @octal_dtr_enable: [FLASH-SPECIFIC] enables SPI NOR octal DTR mode. * @ready: [FLASH-SPECIFIC] check if the flash is ready @@ -556,7 +567,7 @@ struct spi_nor { int (*flash_lock)(struct spi_nor *nor, loff_t ofs, uint64_t len); int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len); - int (*flash_is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len); + int (*flash_is_unlocked)(struct spi_nor *nor, loff_t ofs, uint64_t len); int (*quad_enable)(struct spi_nor *nor); int (*octal_dtr_enable)(struct spi_nor *nor); int (*ready)(struct spi_nor *nor); |