[U-Boot] [PATCH v3 0/5] Add support for Pinebook

This series adds support for the Pinebook, an allwinner A64 laptop produced by Pine64. It also syncs sun50i-a64.dtsi with linux, adds support for mmc delay calibration, R_I2C controller, and addresses the issue with activating video bridge when any of GPIOs is missing.
v2: - sync sun50i-a64.dtsi with linux instead of adding missing nodes - take sun50i-a64-pinebook.dts from linux - don't introduce new Kconfig for A64 MMC calibration - improve code in video bridge uclass to check for presensce of GPIO instead of ingoring EINVAL errors v3: - enable calibration for H6 as well - init ret variable in video_bridge_set_active() - fix order of dts files Makefile - split anx6345 binding into sun50i-a64-pinebook-u-boot.dts - drop speaker_amp node from pinebook dts - drop unnecessary options from defconfig
Vasily Khoruzhick (5): mmc: sunxi: add support for automatic delay calibration dm: video: bridge: don't fail to activate bridge if reset or sleep GPIO is missing sunxi: DT: A64: update device tree file for Allwinner A64 SoC sun50i: A64: add support for R_I2C controller sunxi: DT: add support for Pinebook
arch/arm/dts/Makefile | 1 + arch/arm/dts/sun50i-a64-pinebook-u-boot.dtsi | 15 + arch/arm/dts/sun50i-a64-pinebook.dts | 294 +++++++++++++++++++ arch/arm/dts/sun50i-a64.dtsi | 122 ++++++-- arch/arm/include/asm/arch-sunxi/gpio.h | 1 + arch/arm/include/asm/arch-sunxi/mmc.h | 6 +- arch/arm/mach-sunxi/Kconfig | 1 + board/sunxi/board.c | 6 + configs/pinebook_defconfig | 22 ++ drivers/mmc/sunxi_mmc.c | 21 +- drivers/video/bridge/video-bridge-uclass.c | 16 +- 11 files changed, 479 insertions(+), 26 deletions(-) create mode 100644 arch/arm/dts/sun50i-a64-pinebook-u-boot.dtsi create mode 100644 arch/arm/dts/sun50i-a64-pinebook.dts create mode 100644 configs/pinebook_defconfig

A64 and H6 support automatic delay calibration and Linux driver uses it instead of hardcoded delays. Add support for it to u-boot driver.
Fixes eMMC instability on Pinebook
Signed-off-by: Vasily Khoruzhick anarsoul@gmail.com Acked-by: Maxime Ripard maxime.ripard@bootlin.com Tested-by: Maxime Ripard maxime.ripard@bootlin.com Cc: Vagrant Cascadian vagrant@debian.org --- arch/arm/include/asm/arch-sunxi/mmc.h | 6 +++++- drivers/mmc/sunxi_mmc.c | 21 ++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/arch/arm/include/asm/arch-sunxi/mmc.h b/arch/arm/include/asm/arch-sunxi/mmc.h index d98c53faaa..f2deafddd2 100644 --- a/arch/arm/include/asm/arch-sunxi/mmc.h +++ b/arch/arm/include/asm/arch-sunxi/mmc.h @@ -46,7 +46,9 @@ struct sunxi_mmc { u32 cbda; /* 0x94 */ u32 res2[26]; #if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN50I_H6) - u32 res3[64]; + u32 res3[17]; + u32 samp_dl; + u32 res4[46]; #endif u32 fifo; /* 0x100 / 0x200 FIFO access address */ }; @@ -130,5 +132,7 @@ struct sunxi_mmc { #define SUNXI_MMC_COMMON_CLK_GATE (1 << 16) #define SUNXI_MMC_COMMON_RESET (1 << 18)
+#define SUNXI_MMC_CAL_DL_SW_EN (0x1 << 7) + struct mmc *sunxi_mmc_init(int sdc_no); #endif /* _SUNXI_MMC_H */ diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index 39f15eb423..147eb9b4d5 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -99,11 +99,16 @@ static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz) { unsigned int pll, pll_hz, div, n, oclk_dly, sclk_dly; bool new_mode = false; + bool calibrate = false; u32 val = 0;
if (IS_ENABLED(CONFIG_MMC_SUNXI_HAS_NEW_MODE) && (priv->mmc_no == 2)) new_mode = true;
+#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN50I_H6) + calibrate = true; +#endif + /* * The MMC clock has an extra /2 post-divider when operating in the new * mode. @@ -174,7 +179,11 @@ static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz) val = CCM_MMC_CTRL_MODE_SEL_NEW; setbits_le32(&priv->reg->ntsr, SUNXI_MMC_NTSR_MODE_SEL_NEW); #endif - } else { + } else if (!calibrate) { + /* + * Use hardcoded delay values if controller doesn't support + * calibration + */ val = CCM_MMC_CTRL_OCLK_DLY(oclk_dly) | CCM_MMC_CTRL_SCLK_DLY(sclk_dly); } @@ -228,6 +237,16 @@ static int mmc_config_clock(struct sunxi_mmc_priv *priv, struct mmc *mmc) rval &= ~SUNXI_MMC_CLK_DIVIDER_MASK; writel(rval, &priv->reg->clkcr);
+#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN50I_H6) + /* A64 supports calibration of delays on MMC controller and we + * have to set delay of zero before starting calibration. + * Allwinner BSP driver sets a delay only in the case of + * using HS400 which is not supported by mainline U-Boot or + * Linux at the moment + */ + writel(SUNXI_MMC_CAL_DL_SW_EN, &priv->reg->samp_dl); +#endif + /* Re-enable Clock */ rval |= SUNXI_MMC_CLK_ENABLE; writel(rval, &priv->reg->clkcr);

On Wed, 17 Oct 2018 22:56:47 -0700 Vasily Khoruzhick anarsoul@gmail.com wrote:
A64 and H6 support automatic delay calibration and Linux driver uses it instead of hardcoded delays. Add support for it to u-boot driver.
Fixes eMMC instability on Pinebook
Signed-off-by: Vasily Khoruzhick anarsoul@gmail.com Acked-by: Maxime Ripard maxime.ripard@bootlin.com Tested-by: Maxime Ripard maxime.ripard@bootlin.com Cc: Vagrant Cascadian vagrant@debian.org
Reviewed-by: Andre Przywara andre.przywara@arm.com
Cheers, Andre
arch/arm/include/asm/arch-sunxi/mmc.h | 6 +++++- drivers/mmc/sunxi_mmc.c | 21 ++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/arch/arm/include/asm/arch-sunxi/mmc.h b/arch/arm/include/asm/arch-sunxi/mmc.h index d98c53faaa..f2deafddd2 100644 --- a/arch/arm/include/asm/arch-sunxi/mmc.h +++ b/arch/arm/include/asm/arch-sunxi/mmc.h @@ -46,7 +46,9 @@ struct sunxi_mmc { u32 cbda; /* 0x94 */ u32 res2[26]; #if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN50I_H6)
- u32 res3[64];
- u32 res3[17];
- u32 samp_dl;
- u32 res4[46];
#endif u32 fifo; /* 0x100 / 0x200 FIFO access address */ }; @@ -130,5 +132,7 @@ struct sunxi_mmc { #define SUNXI_MMC_COMMON_CLK_GATE (1 << 16) #define SUNXI_MMC_COMMON_RESET (1 << 18)
+#define SUNXI_MMC_CAL_DL_SW_EN (0x1 << 7)
struct mmc *sunxi_mmc_init(int sdc_no); #endif /* _SUNXI_MMC_H */ diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index 39f15eb423..147eb9b4d5 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -99,11 +99,16 @@ static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz) { unsigned int pll, pll_hz, div, n, oclk_dly, sclk_dly; bool new_mode = false;
bool calibrate = false; u32 val = 0;
if (IS_ENABLED(CONFIG_MMC_SUNXI_HAS_NEW_MODE) &&
(priv->mmc_no == 2)) new_mode = true;
+#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN50I_H6)
- calibrate = true;
+#endif
- /*
- The MMC clock has an extra /2 post-divider when operating
in the new * mode. @@ -174,7 +179,11 @@ static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz) val = CCM_MMC_CTRL_MODE_SEL_NEW; setbits_le32(&priv->reg->ntsr, SUNXI_MMC_NTSR_MODE_SEL_NEW); #endif
- } else {
- } else if (!calibrate) {
/*
* Use hardcoded delay values if controller doesn't
support
* calibration
val = CCM_MMC_CTRL_OCLK_DLY(oclk_dly) | CCM_MMC_CTRL_SCLK_DLY(sclk_dly); }*/
@@ -228,6 +237,16 @@ static int mmc_config_clock(struct sunxi_mmc_priv *priv, struct mmc *mmc) rval &= ~SUNXI_MMC_CLK_DIVIDER_MASK; writel(rval, &priv->reg->clkcr);
+#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN50I_H6)
- /* A64 supports calibration of delays on MMC controller and
we
* have to set delay of zero before starting calibration.
* Allwinner BSP driver sets a delay only in the case of
* using HS400 which is not supported by mainline U-Boot or
* Linux at the moment
*/
- writel(SUNXI_MMC_CAL_DL_SW_EN, &priv->reg->samp_dl);
+#endif
- /* Re-enable Clock */ rval |= SUNXI_MMC_CLK_ENABLE; writel(rval, &priv->reg->clkcr);

Both GPIOs are optional, so we shouldn't fail if any is missing. Without this fix reset is not deasserted if sleep GPIO is missing.
Signed-off-by: Vasily Khoruzhick anarsoul@gmail.com Acked-by: Maxime Ripard maxime.ripard@bootlin.com Tested-by: Maxime Ripard maxime.ripard@bootlin.com Cc: Vagrant Cascadian vagrant@debian.org --- drivers/video/bridge/video-bridge-uclass.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/video/bridge/video-bridge-uclass.c b/drivers/video/bridge/video-bridge-uclass.c index cd4959cc71..5fecb4cfd5 100644 --- a/drivers/video/bridge/video-bridge-uclass.c +++ b/drivers/video/bridge/video-bridge-uclass.c @@ -106,13 +106,19 @@ static int video_bridge_pre_probe(struct udevice *dev) int video_bridge_set_active(struct udevice *dev, bool active) { struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev); - int ret; + int ret = 0;
debug("%s: %d\n", __func__, active); - ret = dm_gpio_set_value(&uc_priv->sleep, !active); - if (ret) - return ret; - if (active) { + if (uc_priv->sleep.dev) { + ret = dm_gpio_set_value(&uc_priv->sleep, !active); + if (ret) + return ret; + } + + if (!active) + return 0; + + if (uc_priv->reset.dev) { ret = dm_gpio_set_value(&uc_priv->reset, true); if (ret) return ret;

On Wed, 17 Oct 2018 22:56:48 -0700 Vasily Khoruzhick anarsoul@gmail.com wrote:
Both GPIOs are optional, so we shouldn't fail if any is missing. Without this fix reset is not deasserted if sleep GPIO is missing.
Signed-off-by: Vasily Khoruzhick anarsoul@gmail.com Acked-by: Maxime Ripard maxime.ripard@bootlin.com Tested-by: Maxime Ripard maxime.ripard@bootlin.com Cc: Vagrant Cascadian vagrant@debian.org
Reviewed-by: Andre Przywara andre.przywara@arm.com
Thanks! Andre.
drivers/video/bridge/video-bridge-uclass.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/video/bridge/video-bridge-uclass.c b/drivers/video/bridge/video-bridge-uclass.c index cd4959cc71..5fecb4cfd5 100644 --- a/drivers/video/bridge/video-bridge-uclass.c +++ b/drivers/video/bridge/video-bridge-uclass.c @@ -106,13 +106,19 @@ static int video_bridge_pre_probe(struct udevice *dev) int video_bridge_set_active(struct udevice *dev, bool active) { struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
- int ret;
int ret = 0;
debug("%s: %d\n", __func__, active);
- ret = dm_gpio_set_value(&uc_priv->sleep, !active);
- if (ret)
return ret;
- if (active) {
- if (uc_priv->sleep.dev) {
ret = dm_gpio_set_value(&uc_priv->sleep, !active);
if (ret)
return ret;
- }
- if (!active)
return 0;
- if (uc_priv->reset.dev) { ret = dm_gpio_set_value(&uc_priv->reset, true); if (ret) return ret;

Updates the device tree file from the the Linux tree as of v4.19-rc4, exactly Linux commit:
commit 7876320f8880 (tag: v4.19-rc4) Author: Linus Torvalds torvalds@linux-foundation.org Date: Sun Sep 16 11:52:37 2018 -0700
Linux 4.19-rc4
Signed-off-by: Vasily Khoruzhick anarsoul@gmail.com Acked-by: Maxime Ripard maxime.ripard@bootlin.com Tested-by: Maxime Ripard maxime.ripard@bootlin.com Cc: Vagrant Cascadian vagrant@debian.org --- arch/arm/dts/sun50i-a64.dtsi | 122 +++++++++++++++++++++++++++++------ 1 file changed, 103 insertions(+), 19 deletions(-)
diff --git a/arch/arm/dts/sun50i-a64.dtsi b/arch/arm/dts/sun50i-a64.dtsi index 7a083637c4..d3daf90a87 100644 --- a/arch/arm/dts/sun50i-a64.dtsi +++ b/arch/arm/dts/sun50i-a64.dtsi @@ -43,9 +43,12 @@ */
#include <dt-bindings/clock/sun50i-a64-ccu.h> +#include <dt-bindings/clock/sun8i-de2.h> #include <dt-bindings/clock/sun8i-r-ccu.h> #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/reset/sun50i-a64-ccu.h> +#include <dt-bindings/reset/sun8i-de2.h> +#include <dt-bindings/reset/sun8i-r-ccu.h>
/ { interrupt-parent = <&gic>; @@ -57,17 +60,21 @@ #size-cells = <1>; ranges;
-/* - * The pipeline mixer0-lcd0 depends on clock CLK_MIXER0 from DE2 CCU. - * However there is no support for this clock on A64 yet, so we depend - * on the upstream clocks here to keep them (and thus CLK_MIXER0) up. - */ simplefb_lcd: framebuffer-lcd { compatible = "allwinner,simple-framebuffer", "simple-framebuffer"; allwinner,pipeline = "mixer0-lcd0"; clocks = <&ccu CLK_TCON0>, - <&ccu CLK_DE>, <&ccu CLK_BUS_DE>; + <&display_clocks CLK_MIXER0>; + status = "disabled"; + }; + + simplefb_hdmi: framebuffer-hdmi { + compatible = "allwinner,simple-framebuffer", + "simple-framebuffer"; + allwinner,pipeline = "mixer1-lcd1-hdmi"; + clocks = <&display_clocks CLK_MIXER1>, + <&ccu CLK_TCON1>, <&ccu CLK_HDMI>; status = "disabled"; }; }; @@ -168,10 +175,46 @@ #size-cells = <1>; ranges;
+ de2@1000000 { + compatible = "allwinner,sun50i-a64-de2"; + reg = <0x1000000 0x400000>; + allwinner,sram = <&de2_sram 1>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x1000000 0x400000>; + + display_clocks: clock@0 { + compatible = "allwinner,sun50i-a64-de2-clk"; + reg = <0x0 0x100000>; + clocks = <&ccu CLK_DE>, + <&ccu CLK_BUS_DE>; + clock-names = "mod", + "bus"; + resets = <&ccu RST_BUS_DE>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + }; + syscon: syscon@1c00000 { - compatible = "allwinner,sun50i-a64-system-controller", - "syscon"; + compatible = "allwinner,sun50i-a64-system-control"; reg = <0x01c00000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + sram_c: sram@18000 { + compatible = "mmio-sram"; + reg = <0x00018000 0x28000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x00018000 0x28000>; + + de2_sram: sram-section@0 { + compatible = "allwinner,sun50i-a64-sram-c"; + reg = <0x0000 0x28000>; + }; + }; };
dma: dma-controller@1c02000 { @@ -364,6 +407,11 @@ bias-pull-up; };
+ pwm_pin: pwm_pin { + pins = "PD22"; + function = "pwm"; + }; + rmii_pins: rmii_pins { pins = "PD10", "PD11", "PD13", "PD14", "PD17", "PD18", "PD19", "PD20", "PD22", "PD23"; @@ -474,15 +522,6 @@ status = "disabled"; };
- pwm: pwm@1c21400 { - compatible = "allwinner,sun50i-a64-pwm", - "allwinner,sun5i-a13-pwm"; - reg = <0x01c21400 0x8>; - clocks = <&osc24M>; - #pwm-cells = <3>; - status = "disabled"; - }; - uart0: serial@1c28000 { compatible = "snps,dw-apb-uart"; reg = <0x01c28000 0x400>; @@ -617,8 +656,6 @@ clocks = <&ccu CLK_BUS_EMAC>; clock-names = "stmmaceth"; status = "disabled"; - #address-cells = <1>; - #size-cells = <0>;
mdio: mdio { compatible = "snps,dwmac-mdio"; @@ -638,11 +675,25 @@ #interrupt-cells = <3>; };
+ pwm: pwm@1c21400 { + compatible = "allwinner,sun50i-a64-pwm", + "allwinner,sun5i-a13-pwm"; + reg = <0x01c21400 0x400>; + clocks = <&osc24M>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_pin>; + #pwm-cells = <3>; + status = "disabled"; + }; + rtc: rtc@1f00000 { compatible = "allwinner,sun6i-a31-rtc"; reg = <0x01f00000 0x54>; interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>; + clock-output-names = "rtc-osc32k", "rtc-osc32k-out"; + clocks = <&osc32k>; + #clock-cells = <1>; };
r_intc: interrupt-controller@1f00c00 { @@ -664,6 +715,29 @@ #reset-cells = <1>; };
+ r_i2c: i2c@1f02400 { + compatible = "allwinner,sun50i-a64-i2c", + "allwinner,sun6i-a31-i2c"; + reg = <0x01f02400 0x400>; + interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&r_ccu CLK_APB0_I2C>; + resets = <&r_ccu RST_APB0_I2C>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + r_pwm: pwm@1f03800 { + compatible = "allwinner,sun50i-a64-pwm", + "allwinner,sun5i-a13-pwm"; + reg = <0x01f03800 0x400>; + clocks = <&osc24M>; + pinctrl-names = "default"; + pinctrl-0 = <&r_pwm_pin>; + #pwm-cells = <3>; + status = "disabled"; + }; + r_pio: pinctrl@1f02c00 { compatible = "allwinner,sun50i-a64-r-pinctrl"; reg = <0x01f02c00 0x400>; @@ -675,6 +749,16 @@ interrupt-controller; #interrupt-cells = <3>;
+ r_i2c_pins_a: i2c-a { + pins = "PL8", "PL9"; + function = "s_i2c"; + }; + + r_pwm_pin: pwm { + pins = "PL10"; + function = "s_pwm"; + }; + r_rsb_pins: rsb { pins = "PL0", "PL1"; function = "s_rsb";

On Thu, Oct 18, 2018 at 11:30 AM Vasily Khoruzhick anarsoul@gmail.com wrote:
Updates the device tree file from the the Linux tree as of v4.19-rc4, exactly Linux commit:
commit 7876320f8880 (tag: v4.19-rc4) Author: Linus Torvalds torvalds@linux-foundation.org Date: Sun Sep 16 11:52:37 2018 -0700
Linux 4.19-rc4
Signed-off-by: Vasily Khoruzhick anarsoul@gmail.com Acked-by: Maxime Ripard maxime.ripard@bootlin.com Tested-by: Maxime Ripard maxime.ripard@bootlin.com Cc: Vagrant Cascadian vagrant@debian.org
arch/arm/dts/sun50i-a64.dtsi | 122 +++++++++++++++++++++++++++++------
Better to pull all a64 files including dts(if there any) in one patch and also this will anyway apply in next MW so try to look for release tag(if that available).

Allwinner A64 has a I2C controller, which is in the R_ MMIO zone and has two groups of pinmuxes on PL bank, so it's called R_I2C.
Add support for this I2C controller and the pinmux which doesn't conflict with RSB.
Signed-off-by: Vasily Khoruzhick anarsoul@gmail.com Acked-by: Maxime Ripard maxime.ripard@bootlin.com Tested-by: Maxime Ripard maxime.ripard@bootlin.com Cc: Vagrant Cascadian vagrant@debian.org --- arch/arm/include/asm/arch-sunxi/gpio.h | 1 + arch/arm/mach-sunxi/Kconfig | 1 + board/sunxi/board.c | 6 ++++++ 3 files changed, 8 insertions(+)
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index 6a5eafc3d3..2daf23f6f5 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -211,6 +211,7 @@ enum sunxi_gpio_number { #define SUN8I_H3_GPL_R_TWI 2 #define SUN8I_A23_GPL_R_TWI 3 #define SUN8I_GPL_R_UART 2 +#define SUN50I_GPL_R_TWI 2
#define SUN9I_GPN_R_RSB 3
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 686f38fec4..7ba429c744 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -272,6 +272,7 @@ config MACH_SUN50I select ARM64 select DM_I2C select PHY_SUN4I_USB + select SUN6I_PRCM select SUNXI_DE2 select SUNXI_GEN_SUN6I select SUPPORT_SPL diff --git a/board/sunxi/board.c b/board/sunxi/board.c index d1d7f9f400..90f8bc0a6e 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -168,10 +168,16 @@ void i2c_init_board(void) #endif
#ifdef CONFIG_R_I2C_ENABLE +#ifdef CONFIG_MACH_SUN50I + clock_twi_onoff(5, 1); + sunxi_gpio_set_cfgpin(SUNXI_GPL(8), SUN50I_GPL_R_TWI); + sunxi_gpio_set_cfgpin(SUNXI_GPL(9), SUN50I_GPL_R_TWI); +#else clock_twi_onoff(5, 1); sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_H3_GPL_R_TWI); sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN8I_H3_GPL_R_TWI); #endif +#endif }
#if defined(CONFIG_ENV_IS_IN_MMC) && defined(CONFIG_ENV_IS_IN_FAT)

Pinebook is a laptop produced by Pine64, with USB-connected keyboard, USB-connected touchpad and an eDP LCD panel connected via a RGB-eDP bridge from Analogix.
Signed-off-by: Vasily Khoruzhick anarsoul@gmail.com Acked-by: Maxime Ripard maxime.ripard@bootlin.com Tested-by: Maxime Ripard maxime.ripard@bootlin.com Cc: Vagrant Cascadian vagrant@debian.org --- arch/arm/dts/Makefile | 1 + arch/arm/dts/sun50i-a64-pinebook-u-boot.dtsi | 15 + arch/arm/dts/sun50i-a64-pinebook.dts | 294 +++++++++++++++++++ configs/pinebook_defconfig | 22 ++ 4 files changed, 332 insertions(+) create mode 100644 arch/arm/dts/sun50i-a64-pinebook-u-boot.dtsi create mode 100644 arch/arm/dts/sun50i-a64-pinebook.dts create mode 100644 configs/pinebook_defconfig
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index dfe9335a04..6b8ee81059 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -404,6 +404,7 @@ dtb-$(CONFIG_MACH_SUN50I) += \ sun50i-a64-orangepi-win.dtb \ sun50i-a64-pine64-plus.dtb \ sun50i-a64-pine64.dtb \ + sun50i-a64-pinebook.dtb \ sun50i-a64-sopine-baseboard.dtb dtb-$(CONFIG_MACH_SUN9I) += \ sun9i-a80-optimus.dtb \ diff --git a/arch/arm/dts/sun50i-a64-pinebook-u-boot.dtsi b/arch/arm/dts/sun50i-a64-pinebook-u-boot.dtsi new file mode 100644 index 0000000000..a99b7171d0 --- /dev/null +++ b/arch/arm/dts/sun50i-a64-pinebook-u-boot.dtsi @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2018 Vasily Khoruzhick anarsoul@gmail.com + * + */ + +/* The ANX6345 eDP-bridge is on r_i2c */ +&r_i2c { + anx6345: edp-bridge@38 { + compatible = "analogix,anx6345"; + reg = <0x38>; + reset-gpios = <&pio 3 24 GPIO_ACTIVE_LOW>; /* PD24 */ + status = "okay"; + }; +}; diff --git a/arch/arm/dts/sun50i-a64-pinebook.dts b/arch/arm/dts/sun50i-a64-pinebook.dts new file mode 100644 index 0000000000..a3b0526ef6 --- /dev/null +++ b/arch/arm/dts/sun50i-a64-pinebook.dts @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2017 Icenowy Zheng icenowy@aosc.xyz + * Copyright (C) 2018 Vasily Khoruzhick anarsoul@gmail.com + * + */ + +/dts-v1/; + +#include "sun50i-a64.dtsi" + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> +#include <dt-bindings/pwm/pwm.h> + +/ { + model = "Pinebook"; + compatible = "pine64,pinebook", "allwinner,sun50i-a64"; + + aliases { + serial0 = &uart0; + ethernet0 = &rtl8723cs; + }; + + vdd_bl: regulator@0 { + compatible = "regulator-fixed"; + regulator-name = "bl-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&pio 7 6 GPIO_ACTIVE_HIGH>; /* PH6 */ + enable-active-high; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm 0 50000 0>; + brightness-levels = <0 5 10 15 20 30 40 55 70 85 100>; + default-brightness-level = <2>; + enable-gpios = <&pio 3 23 GPIO_ACTIVE_HIGH>; /* PD23 */ + power-supply = <&vdd_bl>; + }; + + chosen { + stdout-path = "serial0:115200n8"; + + framebuffer-lcd { + panel-supply = <®_dc1sw>; + dvdd25-supply = <®_dldo2>; + dvdd12-supply = <®_fldo1>; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + + lid_switch { + label = "Lid Switch"; + gpios = <&r_pio 0 12 GPIO_ACTIVE_LOW>; /* PL12 */ + linux,input-type = <EV_SW>; + linux,code = <SW_LID>; + linux,can-disable; + wakeup-source; + }; + }; + + reg_vcc3v3: vcc3v3 { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + wifi_pwrseq: wifi_pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */ + }; +}; + +&ehci0 { + phys = <&usbphy 0>; + phy-names = "usb"; + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins>; + vmmc-supply = <®_dcdc1>; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; + disable-wp; + bus-width = <4>; + status = "okay"; +}; + +&mmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + vmmc-supply = <®_dldo4>; + vqmmc-supply = <®_eldo1>; + mmc-pwrseq = <&wifi_pwrseq>; + bus-width = <4>; + non-removable; + status = "okay"; + + rtl8723cs: wifi@1 { + reg = <1>; + }; +}; + +&mmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins>; + vmmc-supply = <®_dcdc1>; + vqmmc-supply = <®_eldo1>; + bus-width = <8>; + non-removable; + cap-mmc-hw-reset; + mmc-hs200-1_8v; + status = "okay"; +}; + +&ohci0 { + phys = <&usbphy 0>; + phy-names = "usb"; + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&pwm { + status = "okay"; +}; + +&r_rsb { + status = "okay"; + + axp803: pmic@3a3 { + compatible = "x-powers,axp803"; + reg = <0x3a3>; + interrupt-parent = <&r_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +/* The ANX6345 eDP-bridge is on r_i2c */ +&r_i2c { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&r_i2c_pins_a>; + status = "okay"; +}; + +#include "axp803.dtsi" + +®_aldo1 { + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-name = "vcc-csi"; +}; + +®_aldo2 { + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-pl"; +}; + +®_aldo3 { + regulator-always-on; + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-pll-avcc"; +}; + +®_dc1sw { + regulator-name = "vcc-lcd"; +}; + +®_dcdc1 { + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-3v3"; +}; + +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1300000>; + regulator-name = "vdd-cpux"; +}; + +/* DCDC3 is polyphased with DCDC2 */ + +®_dcdc5 { + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-name = "vcc-dram"; +}; + +®_dcdc6 { + regulator-always-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-name = "vdd-sys"; +}; + +®_dldo1 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-hdmi"; +}; + +®_dldo2 { + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-name = "vcc-edp"; +}; + +®_dldo3 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "avdd-csi"; +}; + +®_dldo4 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-wifi"; +}; + +®_eldo1 { + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "cpvdd"; +}; + +®_eldo3 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vdd-1v8-csi"; +}; + +®_fldo1 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-name = "vcc-1v2-hsic"; +}; + +®_fldo2 { + regulator-always-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-name = "vdd-cpus"; +}; + +®_ldo_io0 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-usb"; + status = "okay"; +}; + +®_rtc_ldo { + regulator-name = "vcc-rtc"; +}; + +&simplefb_hdmi { + vcc-hdmi-supply = <®_dldo1>; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usb_otg { + dr_mode = "host"; +}; + +&usbphy { + usb0_vbus-supply = <®_ldo_io0>; + usb1_vbus-supply = <®_ldo_io0>; + status = "okay"; +}; diff --git a/configs/pinebook_defconfig b/configs/pinebook_defconfig new file mode 100644 index 0000000000..5294dbd2eb --- /dev/null +++ b/configs/pinebook_defconfig @@ -0,0 +1,22 @@ +CONFIG_ARM=y +CONFIG_ARCH_SUNXI=y +CONFIG_SPL=y +CONFIG_MACH_SUN50I=y +CONFIG_SUNXI_DRAM_LPDDR3_STOCK=y +CONFIG_DRAM_CLK=552 +CONFIG_DRAM_ZQ=3881949 +CONFIG_MMC_SUNXI_SLOT_EXTRA=2 +CONFIG_R_I2C_ENABLE=y +# CONFIG_CMD_FLASH is not set +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set +CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-pinebook" +CONFIG_DM_REGULATOR=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_PWM=y +CONFIG_PWM_SUNXI=y +CONFIG_USB_EHCI_HCD=y +CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y +# CONFIG_USB_GADGET is not set +CONFIG_VIDEO_BRIDGE=y +CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345=y

On 2018-10-17, Vasily Khoruzhick anarsoul@gmail.com wrote:
Pinebook is a laptop produced by Pine64, with USB-connected keyboard, USB-connected touchpad and an eDP LCD panel connected via a RGB-eDP bridge from Analogix.
Signed-off-by: Vasily Khoruzhick anarsoul@gmail.com Acked-by: Maxime Ripard maxime.ripard@bootlin.com Tested-by: Maxime Ripard maxime.ripard@bootlin.com Cc: Vagrant Cascadian vagrant@debian.org
Working great on my pinebook! Thanks!
Depends on the sunxi-pwm fixes recently posted for working LCD backlight at the u-boot prompt:
https://patchwork.ozlabs.org/project/uboot/list/?series=71167
Tested-by: Vagrant Cascadian vagrant@debian.org
live well, vagrant
arch/arm/dts/Makefile | 1 + arch/arm/dts/sun50i-a64-pinebook-u-boot.dtsi | 15 + arch/arm/dts/sun50i-a64-pinebook.dts | 294 +++++++++++++++++++ configs/pinebook_defconfig | 22 ++ 4 files changed, 332 insertions(+) create mode 100644 arch/arm/dts/sun50i-a64-pinebook-u-boot.dtsi create mode 100644 arch/arm/dts/sun50i-a64-pinebook.dts create mode 100644 configs/pinebook_defconfig
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index dfe9335a04..6b8ee81059 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -404,6 +404,7 @@ dtb-$(CONFIG_MACH_SUN50I) += \ sun50i-a64-orangepi-win.dtb \ sun50i-a64-pine64-plus.dtb \ sun50i-a64-pine64.dtb \
- sun50i-a64-pinebook.dtb \ sun50i-a64-sopine-baseboard.dtb
dtb-$(CONFIG_MACH_SUN9I) += \ sun9i-a80-optimus.dtb \ diff --git a/arch/arm/dts/sun50i-a64-pinebook-u-boot.dtsi b/arch/arm/dts/sun50i-a64-pinebook-u-boot.dtsi new file mode 100644 index 0000000000..a99b7171d0 --- /dev/null +++ b/arch/arm/dts/sun50i-a64-pinebook-u-boot.dtsi @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/*
- Copyright (C) 2018 Vasily Khoruzhick anarsoul@gmail.com
- */
+/* The ANX6345 eDP-bridge is on r_i2c */ +&r_i2c {
- anx6345: edp-bridge@38 {
compatible = "analogix,anx6345";
reg = <0x38>;
reset-gpios = <&pio 3 24 GPIO_ACTIVE_LOW>; /* PD24 */
status = "okay";
- };
+}; diff --git a/arch/arm/dts/sun50i-a64-pinebook.dts b/arch/arm/dts/sun50i-a64-pinebook.dts new file mode 100644 index 0000000000..a3b0526ef6 --- /dev/null +++ b/arch/arm/dts/sun50i-a64-pinebook.dts @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/*
- Copyright (C) 2017 Icenowy Zheng icenowy@aosc.xyz
- Copyright (C) 2018 Vasily Khoruzhick anarsoul@gmail.com
- */
+/dts-v1/;
+#include "sun50i-a64.dtsi"
+#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> +#include <dt-bindings/pwm/pwm.h>
+/ {
- model = "Pinebook";
- compatible = "pine64,pinebook", "allwinner,sun50i-a64";
- aliases {
serial0 = &uart0;
ethernet0 = &rtl8723cs;
- };
- vdd_bl: regulator@0 {
compatible = "regulator-fixed";
regulator-name = "bl-3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&pio 7 6 GPIO_ACTIVE_HIGH>; /* PH6 */
enable-active-high;
- };
- backlight: backlight {
compatible = "pwm-backlight";
pwms = <&pwm 0 50000 0>;
brightness-levels = <0 5 10 15 20 30 40 55 70 85 100>;
default-brightness-level = <2>;
enable-gpios = <&pio 3 23 GPIO_ACTIVE_HIGH>; /* PD23 */
power-supply = <&vdd_bl>;
- };
- chosen {
stdout-path = "serial0:115200n8";
framebuffer-lcd {
panel-supply = <®_dc1sw>;
dvdd25-supply = <®_dldo2>;
dvdd12-supply = <®_fldo1>;
};
- };
- gpio_keys {
compatible = "gpio-keys";
lid_switch {
label = "Lid Switch";
gpios = <&r_pio 0 12 GPIO_ACTIVE_LOW>; /* PL12 */
linux,input-type = <EV_SW>;
linux,code = <SW_LID>;
linux,can-disable;
wakeup-source;
};
- };
- reg_vcc3v3: vcc3v3 {
compatible = "regulator-fixed";
regulator-name = "vcc3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
- };
- wifi_pwrseq: wifi_pwrseq {
compatible = "mmc-pwrseq-simple";
reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */
- };
+};
+&ehci0 {
- phys = <&usbphy 0>;
- phy-names = "usb";
- status = "okay";
+};
+&ehci1 {
- status = "okay";
+};
+&mmc0 {
- pinctrl-names = "default";
- pinctrl-0 = <&mmc0_pins>;
- vmmc-supply = <®_dcdc1>;
- cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
- disable-wp;
- bus-width = <4>;
- status = "okay";
+};
+&mmc1 {
- pinctrl-names = "default";
- pinctrl-0 = <&mmc1_pins>;
- vmmc-supply = <®_dldo4>;
- vqmmc-supply = <®_eldo1>;
- mmc-pwrseq = <&wifi_pwrseq>;
- bus-width = <4>;
- non-removable;
- status = "okay";
- rtl8723cs: wifi@1 {
reg = <1>;
- };
+};
+&mmc2 {
- pinctrl-names = "default";
- pinctrl-0 = <&mmc2_pins>;
- vmmc-supply = <®_dcdc1>;
- vqmmc-supply = <®_eldo1>;
- bus-width = <8>;
- non-removable;
- cap-mmc-hw-reset;
- mmc-hs200-1_8v;
- status = "okay";
+};
+&ohci0 {
- phys = <&usbphy 0>;
- phy-names = "usb";
- status = "okay";
+};
+&ohci1 {
- status = "okay";
+};
+&pwm {
- status = "okay";
+};
+&r_rsb {
- status = "okay";
- axp803: pmic@3a3 {
compatible = "x-powers,axp803";
reg = <0x3a3>;
interrupt-parent = <&r_intc>;
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
- };
+};
+/* The ANX6345 eDP-bridge is on r_i2c */ +&r_i2c {
- clock-frequency = <100000>;
- pinctrl-names = "default";
- pinctrl-0 = <&r_i2c_pins_a>;
- status = "okay";
+};
+#include "axp803.dtsi"
+®_aldo1 {
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <2800000>;
- regulator-name = "vcc-csi";
+};
+®_aldo2 {
- regulator-always-on;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- regulator-name = "vcc-pl";
+};
+®_aldo3 {
- regulator-always-on;
- regulator-min-microvolt = <2700000>;
- regulator-max-microvolt = <3300000>;
- regulator-name = "vcc-pll-avcc";
+};
+®_dc1sw {
- regulator-name = "vcc-lcd";
+};
+®_dcdc1 {
- regulator-always-on;
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-name = "vcc-3v3";
+};
+®_dcdc2 {
- regulator-always-on;
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1300000>;
- regulator-name = "vdd-cpux";
+};
+/* DCDC3 is polyphased with DCDC2 */
+®_dcdc5 {
- regulator-always-on;
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- regulator-name = "vcc-dram";
+};
+®_dcdc6 {
- regulator-always-on;
- regulator-min-microvolt = <1100000>;
- regulator-max-microvolt = <1100000>;
- regulator-name = "vdd-sys";
+};
+®_dldo1 {
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-name = "vcc-hdmi";
+};
+®_dldo2 {
- regulator-min-microvolt = <2500000>;
- regulator-max-microvolt = <2500000>;
- regulator-name = "vcc-edp";
+};
+®_dldo3 {
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-name = "avdd-csi";
+};
+®_dldo4 {
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-name = "vcc-wifi";
+};
+®_eldo1 {
- regulator-always-on;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-name = "cpvdd";
+};
+®_eldo3 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-name = "vdd-1v8-csi";
+};
+®_fldo1 {
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- regulator-name = "vcc-1v2-hsic";
+};
+®_fldo2 {
- regulator-always-on;
- regulator-min-microvolt = <1100000>;
- regulator-max-microvolt = <1100000>;
- regulator-name = "vdd-cpus";
+};
+®_ldo_io0 {
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-name = "vcc-usb";
- status = "okay";
+};
+®_rtc_ldo {
- regulator-name = "vcc-rtc";
+};
+&simplefb_hdmi {
- vcc-hdmi-supply = <®_dldo1>;
+};
+&uart0 {
- pinctrl-names = "default";
- pinctrl-0 = <&uart0_pins_a>;
- status = "okay";
+};
+&usb_otg {
- dr_mode = "host";
+};
+&usbphy {
- usb0_vbus-supply = <®_ldo_io0>;
- usb1_vbus-supply = <®_ldo_io0>;
- status = "okay";
+}; diff --git a/configs/pinebook_defconfig b/configs/pinebook_defconfig new file mode 100644 index 0000000000..5294dbd2eb --- /dev/null +++ b/configs/pinebook_defconfig @@ -0,0 +1,22 @@ +CONFIG_ARM=y +CONFIG_ARCH_SUNXI=y +CONFIG_SPL=y +CONFIG_MACH_SUN50I=y +CONFIG_SUNXI_DRAM_LPDDR3_STOCK=y +CONFIG_DRAM_CLK=552 +CONFIG_DRAM_ZQ=3881949 +CONFIG_MMC_SUNXI_SLOT_EXTRA=2 +CONFIG_R_I2C_ENABLE=y +# CONFIG_CMD_FLASH is not set +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set +CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-pinebook" +CONFIG_DM_REGULATOR=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_PWM=y +CONFIG_PWM_SUNXI=y +CONFIG_USB_EHCI_HCD=y +CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y +# CONFIG_USB_GADGET is not set +CONFIG_VIDEO_BRIDGE=y
+CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345=y
2.19.0
participants (4)
-
Andre Przywara
-
Jagan Teki
-
Vagrant Cascadian
-
Vasily Khoruzhick