Merge branch '2023-02-10-assorted-updates-and-additions'

- DM_SERIAL conversion for bcm7xxx, button input driver, qcom updates,
  environment and network related cleanup, ftmac100 update, add a
  IS_ENABLED conversion that was just missed.
This commit is contained in:
Tom Rini 2023-02-10 13:41:27 -05:00
commit a1e6b529e5
49 changed files with 1958 additions and 81 deletions

View file

@ -72,7 +72,7 @@
record { record {
label = "Record"; label = "Record";
/* linux,code = <BTN_0>; */ linux,code = <KEY_RECORD>;
gpios = <&tca6416_2 15 GPIO_ACTIVE_LOW>; gpios = <&tca6416_2 15 GPIO_ACTIVE_LOW>;
}; };

View file

@ -9,7 +9,6 @@
#include "skeleton64.dtsi" #include "skeleton64.dtsi"
#include <dt-bindings/gpio/gpio.h> #include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/pinctrl-snapdragon.h>
/ { / {
model = "Qualcomm Technologies, Inc. Dragonboard 410c"; model = "Qualcomm Technologies, Inc. Dragonboard 410c";
@ -71,7 +70,7 @@
blsp1_uart: uart { blsp1_uart: uart {
function = "blsp1_uart"; function = "blsp1_uart";
pins = "GPIO_4", "GPIO_5"; pins = "GPIO_4", "GPIO_5";
drive-strength = <DRIVE_STRENGTH_8MA>; drive-strength = <8>;
bias-disable; bias-disable;
}; };
}; };

View file

@ -8,7 +8,6 @@
/dts-v1/; /dts-v1/;
#include "skeleton64.dtsi" #include "skeleton64.dtsi"
#include <dt-bindings/pinctrl/pinctrl-snapdragon.h>
/ { / {
model = "Qualcomm Technologies, Inc. DB820c"; model = "Qualcomm Technologies, Inc. DB820c";
@ -71,7 +70,7 @@
blsp8_uart: uart { blsp8_uart: uart {
function = "blsp_uart8"; function = "blsp_uart8";
pins = "GPIO_4", "GPIO_5"; pins = "GPIO_4", "GPIO_5";
drive-strength = <DRIVE_STRENGTH_8MA>; drive-strength = <8>;
bias-disable; bias-disable;
}; };
}; };

View file

@ -8,7 +8,7 @@
/ { / {
gpio_keys: gpio-keys { gpio_keys: gpio-keys {
compatible = "gpio-key"; compatible = "gpio-keys";
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio_keys>; pinctrl-0 = <&pinctrl_gpio_keys>;
status = "disabled"; status = "disabled";

View file

@ -9,7 +9,6 @@
#include "skeleton.dtsi" #include "skeleton.dtsi"
#include <dt-bindings/gpio/gpio.h> #include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/pinctrl-snapdragon.h>
#include <dt-bindings/clock/qcom,ipq4019-gcc.h> #include <dt-bindings/clock/qcom,ipq4019-gcc.h>
#include <dt-bindings/reset/qcom,ipq4019-reset.h> #include <dt-bindings/reset/qcom,ipq4019-reset.h>

View file

@ -9,7 +9,6 @@
#include "skeleton64.dtsi" #include "skeleton64.dtsi"
#include <dt-bindings/gpio/gpio.h> #include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/pinctrl-snapdragon.h>
#include <dt-bindings/clock/qcom,gcc-qcs404.h> #include <dt-bindings/clock/qcom,gcc-qcs404.h>
/ { / {
@ -24,6 +23,11 @@
aliases { aliases {
serial0 = &debug_uart; serial0 = &debug_uart;
i2c0 = &blsp1_i2c0;
i2c1 = &blsp1_i2c1;
i2c2 = &blsp1_i2c2;
i2c3 = &blsp1_i2c3;
i2c4 = &blsp1_i2c4;
}; };
memory { memory {
@ -37,14 +41,165 @@
ranges = <0x0 0x0 0x0 0xffffffff>; ranges = <0x0 0x0 0x0 0xffffffff>;
compatible = "simple-bus"; compatible = "simple-bus";
pinctrl_north@1300000 { soc_gpios: pinctrl_north@1300000 {
compatible = "qcom,qcs404-pinctrl"; compatible = "qcom,qcs404-pinctrl";
reg = <0x1300000 0x200000>; reg = <0x1300000 0x200000>;
gpio-controller;
gpio-count = <120>;
gpio-bank-name="soc";
#gpio-cells = <2>;
blsp1_uart2: uart { blsp1_uart2: uart {
pins = "GPIO_17", "GPIO_18"; pins = "GPIO_17", "GPIO_18";
function = "blsp_uart2"; function = "blsp_uart2";
}; };
blsp1_i2c0_default: blsp1-i2c0-default {
pins = "GPIO_32", "GPIO_33";
function = "blsp_i2c0";
};
blsp1_i2c1_default: blsp1-i2c1-default {
pins = "GPIO_24", "GPIO_25";
function = "blsp_i2c1";
};
blsp1_i2c2_default: blsp1-i2c2-default {
sda {
pins = "GPIO_19";
function = "blsp_i2c_sda_a2";
};
scl {
pins = "GPIO_20";
function = "blsp_i2c_scl_a2";
};
};
blsp1_i2c3_default: blsp1-i2c3-default {
pins = "GPIO_84", "GPIO_85";
function = "blsp_i2c3";
};
blsp1_i2c4_default: blsp1-i2c4-default {
pins = "GPIO_117", "GPIO_118";
function = "blsp_i2c4";
};
ethernet_defaults: ethernet-defaults {
int {
pins = "GPIO_61";
function = "rgmii_int";
bias-disable;
drive-strength = <2>;
};
mdc {
pins = "GPIO_76";
function = "rgmii_mdc";
bias-pull-up;
};
mdio {
pins = "GPIO_75";
function = "rgmii_mdio";
bias-pull-up;
};
tx {
pins = "GPIO_67", "GPIO_66", "GPIO_65", "GPIO_64";
function = "rgmii_tx";
bias-pull-up;
drive-strength = <16>;
};
rx {
pins = "GPIO_73", "GPIO_72", "GPIO_71", "GPIO_70";
function = "rgmii_rx";
bias-disable;
drive-strength = <2>;
};
tx-ctl {
pins = "GPIO_68";
function = "rgmii_ctl";
bias-pull-up;
drive-strength = <16>;
};
rx-ctl {
pins = "GPIO_74";
function = "rgmii_ctl";
bias-disable;
drive-strength = <2>;
};
tx-ck {
pins = "GPIO_63";
function = "rgmii_ck";
bias-pull-up;
drive-strength = <16>;
};
rx-ck {
pins = "GPIO_69";
function = "rgmii_ck";
bias-disable;
drive-strength = <2>;
};
};
};
blsp1_i2c0: i2c@78b5000 {
compatible = "qcom,i2c-qup-v2.2.1";
reg = <0x078b5000 0x600>;
clocks = <&gcc GCC_BLSP1_AHB_CLK>,
<&gcc GCC_BLSP1_QUP0_I2C_APPS_CLK>;
clock-names = "iface", "core";
pinctrl-names = "default";
pinctrl-0 = <&blsp1_i2c0_default>;
#address-cells = <1>;
#size-cells = <0>;
};
blsp1_i2c1: i2c@78b6000 {
compatible = "qcom,i2c-qup-v2.2.1";
reg = <0x078b6000 0x600>;
clocks = <&gcc GCC_BLSP1_AHB_CLK>,
<&gcc GCC_BLSP1_QUP1_I2C_APPS_CLK>;
clock-names = "iface", "core";
pinctrl-names = "default";
pinctrl-0 = <&blsp1_i2c1_default>;
#address-cells = <1>;
#size-cells = <0>;
};
blsp1_i2c2: i2c@78b7000 {
compatible = "qcom,i2c-qup-v2.2.1";
reg = <0x078b7000 0x600>;
clocks = <&gcc GCC_BLSP1_AHB_CLK>,
<&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>;
clock-names = "iface", "core";
pinctrl-names = "default";
pinctrl-0 = <&blsp1_i2c2_default>;
#address-cells = <1>;
#size-cells = <0>;
};
blsp1_i2c3: i2c@78b8000 {
compatible = "qcom,i2c-qup-v2.2.1";
reg = <0x078b8000 0x600>;
clocks = <&gcc GCC_BLSP1_AHB_CLK>,
<&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>;
clock-names = "iface", "core";
pinctrl-names = "default";
pinctrl-0 = <&blsp1_i2c3_default>;
#address-cells = <1>;
#size-cells = <0>;
};
blsp1_i2c4: i2c@78b9000 {
compatible = "qcom,i2c-qup-v2.2.1";
reg = <0x078b9000 0x600>;
clocks = <&gcc GCC_BLSP1_AHB_CLK>,
<&gcc GCC_BLSP1_QUP4_I2C_APPS_CLK>;
clock-names = "iface", "core";
pinctrl-names = "default";
pinctrl-0 = <&blsp1_i2c4_default>;
#address-cells = <1>;
#size-cells = <0>;
}; };
gcc: clock-controller@1800000 { gcc: clock-controller@1800000 {
@ -169,6 +324,47 @@
}; };
}; };
ethernet: ethernet@7a80000 {
compatible = "qcom,qcs404-ethqos";
reg = <0x07a80000 0x10000>,
<0x07a96000 0x100>;
reg-names = "stmmaceth", "rgmii";
clock-names = "stmmaceth", "pclk", "ptp_ref", "rgmii";
clocks = <&gcc GCC_ETH_AXI_CLK>,
<&gcc GCC_ETH_SLAVE_AHB_CLK>,
<&gcc GCC_ETH_PTP_CLK>,
<&gcc GCC_ETH_RGMII_CLK>;
resets = <&reset GCC_EMAC_BCR>;
reset-names = "emac";
snps,tso;
rx-fifo-depth = <4096>;
tx-fifo-depth = <4096>;
snps,reset-gpio = <&soc_gpios 60 GPIO_ACTIVE_LOW>;
snps,reset-active-low;
snps,reset-delays-us = <0 10000 10000>;
pinctrl-names = "default";
pinctrl-0 = <&ethernet_defaults>;
phy-handle = <&phy1>;
phy-mode = "rgmii";
max-speed = <1000>;
mdio {
#address-cells = <0x1>;
#size-cells = <0x0>;
compatible = "snps,dwmac-mdio";
phy1: phy@3 {
compatible = "ethernet-phy-ieee802.3-c22";
device_type = "ethernet-phy";
reg = <0x3>;
};
};
};
spmi@200f000 { spmi@200f000 {
compatible = "qcom,spmi-pmic-arb"; compatible = "qcom,spmi-pmic-arb";
reg = <0x200f000 0x1000 reg = <0x200f000 0x1000

View file

@ -38,6 +38,7 @@
* OTHER DEALINGS IN THE SOFTWARE. * OTHER DEALINGS IN THE SOFTWARE.
*/ */
#include <dt-bindings/input/input.h>
#include "rk3288.dtsi" #include "rk3288.dtsi"
/ { / {
@ -63,6 +64,7 @@
power { power {
gpios = <&gpio0 5 GPIO_ACTIVE_LOW>; gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
label = "GPIO Key Power"; label = "GPIO Key Power";
linux,code = <KEY_POWER>;
linux,input-type = <1>; linux,input-type = <1>;
wakeup-source; wakeup-source;
debounce-interval = <100>; debounce-interval = <100>;

View file

@ -38,6 +38,7 @@
* OTHER DEALINGS IN THE SOFTWARE. * OTHER DEALINGS IN THE SOFTWARE.
*/ */
#include <dt-bindings/input/input.h>
#include "rk3288.dtsi" #include "rk3288.dtsi"
/ { / {
@ -63,6 +64,7 @@
button@0 { button@0 {
gpios = <&gpio0 5 GPIO_ACTIVE_LOW>; gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
label = "GPIO Key Power"; label = "GPIO Key Power";
linux,code = <KEY_POWER>;
linux,input-type = <1>; linux,input-type = <1>;
gpio-key,wakeup = <1>; gpio-key,wakeup = <1>;
debounce-interval = <100>; debounce-interval = <100>;

View file

@ -18,6 +18,9 @@
/* GPLL0 clock control registers */ /* GPLL0 clock control registers */
#define GPLL0_STATUS_ACTIVE BIT(31) #define GPLL0_STATUS_ACTIVE BIT(31)
#define CFG_CLK_SRC_GPLL1 BIT(8)
#define GPLL1_STATUS_ACTIVE BIT(31)
static struct vote_clk gcc_blsp1_ahb_clk = { static struct vote_clk gcc_blsp1_ahb_clk = {
.cbcr_reg = BLSP1_AHB_CBCR, .cbcr_reg = BLSP1_AHB_CBCR,
.ena_vote = APCS_CLOCK_BRANCH_ENA_VOTE, .ena_vote = APCS_CLOCK_BRANCH_ENA_VOTE,
@ -47,6 +50,13 @@ static struct pll_vote_clk gpll0_vote_clk = {
.vote_bit = BIT(0), .vote_bit = BIT(0),
}; };
static struct pll_vote_clk gpll1_vote_clk = {
.status = GPLL1_STATUS,
.status_bit = GPLL1_STATUS_ACTIVE,
.ena_vote = APCS_GPLL_ENA_VOTE,
.vote_bit = BIT(1),
};
static const struct bcr_regs usb30_master_regs = { static const struct bcr_regs usb30_master_regs = {
.cfg_rcgr = USB30_MASTER_CFG_RCGR, .cfg_rcgr = USB30_MASTER_CFG_RCGR,
.cmd_rcgr = USB30_MASTER_CMD_RCGR, .cmd_rcgr = USB30_MASTER_CMD_RCGR,
@ -55,6 +65,22 @@ static const struct bcr_regs usb30_master_regs = {
.D = USB30_MASTER_D, .D = USB30_MASTER_D,
}; };
static const struct bcr_regs emac_regs = {
.cfg_rcgr = EMAC_CFG_RCGR,
.cmd_rcgr = EMAC_CMD_RCGR,
.M = EMAC_M,
.N = EMAC_N,
.D = EMAC_D,
};
static const struct bcr_regs emac_ptp_regs = {
.cfg_rcgr = EMAC_PTP_CFG_RCGR,
.cmd_rcgr = EMAC_PTP_CMD_RCGR,
.M = EMAC_M,
.N = EMAC_N,
.D = EMAC_D,
};
ulong msm_set_rate(struct clk *clk, ulong rate) ulong msm_set_rate(struct clk *clk, ulong rate)
{ {
struct msm_clk_priv *priv = dev_get_priv(clk->dev); struct msm_clk_priv *priv = dev_get_priv(clk->dev);
@ -79,6 +105,20 @@ ulong msm_set_rate(struct clk *clk, ulong rate)
case GCC_SDCC1_AHB_CLK: case GCC_SDCC1_AHB_CLK:
clk_enable_cbc(priv->base + SDCC_AHB_CBCR(1)); clk_enable_cbc(priv->base + SDCC_AHB_CBCR(1));
break; break;
case GCC_ETH_RGMII_CLK:
if (rate == 250000000)
clk_rcg_set_rate_mnd(priv->base, &emac_regs, 2, 0, 0,
CFG_CLK_SRC_GPLL1);
else if (rate == 125000000)
clk_rcg_set_rate_mnd(priv->base, &emac_regs, 4, 0, 0,
CFG_CLK_SRC_GPLL1);
else if (rate == 50000000)
clk_rcg_set_rate_mnd(priv->base, &emac_regs, 10, 0, 0,
CFG_CLK_SRC_GPLL1);
else if (rate == 5000000)
clk_rcg_set_rate_mnd(priv->base, &emac_regs, 2, 1, 50,
CFG_CLK_SRC_GPLL1);
break;
default: default:
return 0; return 0;
} }
@ -111,6 +151,26 @@ int msm_enable(struct clk *clk)
case GCC_USB2A_PHY_SLEEP_CLK: case GCC_USB2A_PHY_SLEEP_CLK:
clk_enable_cbc(priv->base + USB_HS_PHY_CFG_AHB_CBCR); clk_enable_cbc(priv->base + USB_HS_PHY_CFG_AHB_CBCR);
break; break;
case GCC_ETH_PTP_CLK:
/* SPEED_1000: freq -> 250MHz */
clk_enable_cbc(priv->base + ETH_PTP_CBCR);
clk_enable_gpll0(priv->base, &gpll1_vote_clk);
clk_rcg_set_rate_mnd(priv->base, &emac_ptp_regs, 2, 0, 0,
CFG_CLK_SRC_GPLL1);
break;
case GCC_ETH_RGMII_CLK:
/* SPEED_1000: freq -> 250MHz */
clk_enable_cbc(priv->base + ETH_RGMII_CBCR);
clk_enable_gpll0(priv->base, &gpll1_vote_clk);
clk_rcg_set_rate_mnd(priv->base, &emac_regs, 2, 0, 0,
CFG_CLK_SRC_GPLL1);
break;
case GCC_ETH_SLAVE_AHB_CLK:
clk_enable_cbc(priv->base + ETH_SLAVE_AHB_CBCR);
break;
case GCC_ETH_AXI_CLK:
clk_enable_cbc(priv->base + ETH_AXI_CBCR);
break;
default: default:
return 0; return 0;
} }

View file

@ -111,6 +111,30 @@ void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs,
clk_bcr_update(base + regs->cmd_rcgr); clk_bcr_update(base + regs->cmd_rcgr);
} }
/* root set rate for clocks with half integer and mnd_width=0 */
void clk_rcg_set_rate(phys_addr_t base, const struct bcr_regs *regs, int div,
int source)
{
u32 cfg;
/* setup src select and divider */
cfg = readl(base + regs->cfg_rcgr);
cfg &= ~CFG_MASK;
cfg |= source & CFG_CLK_SRC_MASK; /* Select clock source */
/*
* Set the divider; HW permits fraction dividers (+0.5), but
* for simplicity, we will support integers only
*/
if (div)
cfg |= (2 * div - 1) & CFG_DIVIDER_MASK;
writel(cfg, base + regs->cfg_rcgr); /* Write new clock configuration */
/* Inform h/w to start using the new config. */
clk_bcr_update(base + regs->cmd_rcgr);
}
static int msm_clk_probe(struct udevice *dev) static int msm_clk_probe(struct udevice *dev)
{ {
struct msm_clk_priv *priv = dev_get_priv(dev); struct msm_clk_priv *priv = dev_get_priv(dev);

View file

@ -42,5 +42,7 @@ void clk_enable_cbc(phys_addr_t cbcr);
void clk_enable_vote_clk(phys_addr_t base, const struct vote_clk *vclk); void clk_enable_vote_clk(phys_addr_t base, const struct vote_clk *vclk);
void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs, void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs,
int div, int m, int n, int source); int div, int m, int n, int source);
void clk_rcg_set_rate(phys_addr_t base, const struct bcr_regs *regs, int div,
int source);
#endif #endif

View file

@ -12,6 +12,7 @@
/* Clocks: (from CLK_CTL_BASE) */ /* Clocks: (from CLK_CTL_BASE) */
#define GPLL0_STATUS (0x21000) #define GPLL0_STATUS (0x21000)
#define GPLL1_STATUS (0x20000)
#define APCS_GPLL_ENA_VOTE (0x45000) #define APCS_GPLL_ENA_VOTE (0x45000)
#define APCS_CLOCK_BRANCH_ENA_VOTE (0x45004) #define APCS_CLOCK_BRANCH_ENA_VOTE (0x45004)
@ -54,4 +55,17 @@
#define USB2A_PHY_SLEEP_CBCR (0x4102C) #define USB2A_PHY_SLEEP_CBCR (0x4102C)
#define USB_HS_PHY_CFG_AHB_CBCR (0x41030) #define USB_HS_PHY_CFG_AHB_CBCR (0x41030)
/* ETH controller clock control registers */
#define ETH_PTP_CBCR (0x4e004)
#define ETH_RGMII_CBCR (0x4e008)
#define ETH_SLAVE_AHB_CBCR (0x4e00c)
#define ETH_AXI_CBCR (0x4e010)
#define EMAC_PTP_CMD_RCGR (0x4e014)
#define EMAC_PTP_CFG_RCGR (0x4e018)
#define EMAC_CMD_RCGR (0x4e01c)
#define EMAC_CFG_RCGR (0x4e020)
#define EMAC_M (0x4e024)
#define EMAC_N (0x4e028)
#define EMAC_D (0x4e02c)
#endif #endif

View file

@ -22,6 +22,19 @@ static const char * const msm_pinctrl_pins[] = {
static const struct pinctrl_function msm_pinctrl_functions[] = { static const struct pinctrl_function msm_pinctrl_functions[] = {
{"blsp_uart2", 1}, {"blsp_uart2", 1},
{"rgmii_int", 1},
{"rgmii_ck", 1},
{"rgmii_tx", 1},
{"rgmii_ctl", 1},
{"rgmii_rx", 1},
{"rgmii_mdio", 1},
{"rgmii_mdc", 1},
{"blsp_i2c0", 3},
{"blsp_i2c1", 2},
{"blsp_i2c_sda_a2", 3},
{"blsp_i2c_scl_a2", 3},
{"blsp_i2c3", 2},
{"blsp_i2c4", 1},
}; };
static const char *qcs404_get_function_name(struct udevice *dev, static const char *qcs404_get_function_name(struct udevice *dev,

View file

@ -28,8 +28,9 @@ struct msm_pinctrl_priv {
#define TLMM_GPIO_DISABLE BIT(9) #define TLMM_GPIO_DISABLE BIT(9)
static const struct pinconf_param msm_conf_params[] = { static const struct pinconf_param msm_conf_params[] = {
{ "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 3 }, { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 2 },
{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 }, { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 3 },
}; };
static int msm_get_functions_count(struct udevice *dev) static int msm_get_functions_count(struct udevice *dev)
@ -89,6 +90,7 @@ static int msm_pinconf_set(struct udevice *dev, unsigned int pin_selector,
switch (param) { switch (param) {
case PIN_CONFIG_DRIVE_STRENGTH: case PIN_CONFIG_DRIVE_STRENGTH:
argument = (argument / 2) - 1;
clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector), clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector),
TLMM_DRV_STRENGTH_MASK, argument << 6); TLMM_DRV_STRENGTH_MASK, argument << 6);
break; break;
@ -96,6 +98,10 @@ static int msm_pinconf_set(struct udevice *dev, unsigned int pin_selector,
clrbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector), clrbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector),
TLMM_GPIO_PULL_MASK); TLMM_GPIO_PULL_MASK);
break; break;
case PIN_CONFIG_BIAS_PULL_UP:
clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector),
TLMM_GPIO_PULL_MASK, argument);
break;
default: default:
return 0; return 0;
} }

View file

@ -19,7 +19,19 @@ static struct mm_region qcs404_mem_map[] = {
}, { }, {
.virt = 0x80000000UL, /* DDR */ .virt = 0x80000000UL, /* DDR */
.phys = 0x80000000UL, /* DDR */ .phys = 0x80000000UL, /* DDR */
.size = 0x40000000UL, .size = 0x05900000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
}, {
.virt = 0x89600000UL, /* DDR */
.phys = 0x89600000UL, /* DDR */
.size = 0x162000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
}, {
.virt = 0xa0000000UL, /* DDR */
.phys = 0xa0000000UL, /* DDR */
.size = 0x20000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE PTE_BLOCK_INNER_SHARE
}, { }, {

View file

@ -4,6 +4,8 @@
* and sandbox64 builds. * and sandbox64 builds.
*/ */
#include <dt-bindings/input/input.h>
#define USB_CLASS_HUB 9 #define USB_CLASS_HUB 9
/ { / {
@ -36,11 +38,13 @@
btn1 { btn1 {
gpios = <&gpio_a 3 0>; gpios = <&gpio_a 3 0>;
label = "button1"; label = "button1";
linux,code = <BTN_1>;
}; };
btn2 { btn2 {
gpios = <&gpio_a 4 0>; gpios = <&gpio_a 4 0>;
label = "button2"; label = "button2";
linux,code = <BTN_2>;
}; };
}; };

View file

@ -172,11 +172,13 @@
btn1 { btn1 {
gpios = <&gpio_a 3 0>; gpios = <&gpio_a 3 0>;
label = "button1"; label = "button1";
linux,code = <BTN_1>;
}; };
btn2 { btn2 {
gpios = <&gpio_a 4 0>; gpios = <&gpio_a 4 0>;
label = "button2"; label = "button2";
linux,code = <BTN_2>;
}; };
}; };
@ -1537,6 +1539,20 @@
}; };
}; };
ofnode-foreach {
compatible = "foreach";
first {
prop1 = <1>;
prop2 = <2>;
};
second {
prop1 = <1>;
prop2 = <2>;
};
};
osd { osd {
compatible = "sandbox,sandbox_osd"; compatible = "sandbox,sandbox_osd";
}; };

View file

@ -2670,7 +2670,7 @@ static const struct eficonfig_item maintenance_menu_items[] = {
{"Edit Boot Option", eficonfig_process_edit_boot_option}, {"Edit Boot Option", eficonfig_process_edit_boot_option},
{"Change Boot Order", eficonfig_process_change_boot_order}, {"Change Boot Order", eficonfig_process_change_boot_order},
{"Delete Boot Option", eficonfig_process_delete_boot_option}, {"Delete Boot Option", eficonfig_process_delete_boot_option},
#if (CONFIG_IS_ENABLED(EFI_SECURE_BOOT) && IS_ENABLED(CONFIG_EFI_MM_COMM_TEE)) #if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT) && IS_ENABLED(CONFIG_EFI_MM_COMM_TEE))
{"Secure Boot Configuration", eficonfig_process_secure_boot_config}, {"Secure Boot Configuration", eficonfig_process_secure_boot_config},
#endif #endif
{"Quit", eficonfig_process_quit}, {"Quit", eficonfig_process_quit},

View file

@ -40,6 +40,6 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_BCMSTB=y CONFIG_MMC_SDHCI_BCMSTB=y
CONFIG_MTD=y CONFIG_MTD=y
CONFIG_SYS_NS16550_SERIAL=y CONFIG_DM_SERIAL=y
CONFIG_SYS_NS16550_REG_SIZE=-4 CONFIG_SYS_NS16550=y
# CONFIG_EFI_LOADER is not set # CONFIG_EFI_LOADER is not set

View file

@ -44,8 +44,8 @@ CONFIG_MTD=y
CONFIG_DM_SPI_FLASH=y CONFIG_DM_SPI_FLASH=y
CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_SPI_FLASH_STMICRO=y CONFIG_SPI_FLASH_STMICRO=y
CONFIG_SYS_NS16550_SERIAL=y CONFIG_DM_SERIAL=y
CONFIG_SYS_NS16550_REG_SIZE=-4 CONFIG_SYS_NS16550=y
CONFIG_SPI=y CONFIG_SPI=y
CONFIG_DM_SPI=y CONFIG_DM_SPI=y
CONFIG_BCMSTB_SPI=y CONFIG_BCMSTB_SPI=y

View file

@ -44,6 +44,7 @@ CONFIG_DM_PMIC=y
CONFIG_PMIC_QCOM=y CONFIG_PMIC_QCOM=y
CONFIG_DM_RESET=y CONFIG_DM_RESET=y
CONFIG_MSM_SERIAL=y CONFIG_MSM_SERIAL=y
CONFIG_MSM_GPIO=y
CONFIG_SPMI_MSM=y CONFIG_SPMI_MSM=y
CONFIG_USB=y CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_HCD=y

View file

@ -31,6 +31,12 @@ ${CROSS_COMPILE}strip u-boot
Run Run
=== ===
To tell U-Boot which serial port to use for its console, set the
"stdout-path" property in the "/chosen" node of the BOLT-generated
device tree. For example:
BOLT> dt add prop chosen stdout-path s serial0:115200n8
Flash the u-boot binary into board storage, then invoke it from BOLT. Flash the u-boot binary into board storage, then invoke it from BOLT.
For example: For example:

View file

@ -13,6 +13,7 @@
struct button_gpio_priv { struct button_gpio_priv {
struct gpio_desc gpio; struct gpio_desc gpio;
int linux_code;
}; };
static enum button_state_t button_gpio_get_state(struct udevice *dev) static enum button_state_t button_gpio_get_state(struct udevice *dev)
@ -29,6 +30,17 @@ static enum button_state_t button_gpio_get_state(struct udevice *dev)
return ret ? BUTTON_ON : BUTTON_OFF; return ret ? BUTTON_ON : BUTTON_OFF;
} }
static int button_gpio_get_code(struct udevice *dev)
{
struct button_gpio_priv *priv = dev_get_priv(dev);
int code = priv->linux_code;
if (!code)
return -ENODATA;
return code;
}
static int button_gpio_probe(struct udevice *dev) static int button_gpio_probe(struct udevice *dev)
{ {
struct button_uc_plat *uc_plat = dev_get_uclass_plat(dev); struct button_uc_plat *uc_plat = dev_get_uclass_plat(dev);
@ -43,7 +55,9 @@ static int button_gpio_probe(struct udevice *dev)
if (ret) if (ret)
return ret; return ret;
return 0; ret = dev_read_u32(dev, "linux,code", &priv->linux_code);
return ret;
} }
static int button_gpio_remove(struct udevice *dev) static int button_gpio_remove(struct udevice *dev)
@ -92,6 +106,7 @@ static int button_gpio_bind(struct udevice *parent)
static const struct button_ops button_gpio_ops = { static const struct button_ops button_gpio_ops = {
.get_state = button_gpio_get_state, .get_state = button_gpio_get_state,
.get_code = button_gpio_get_code,
}; };
static const struct udevice_id button_gpio_ids[] = { static const struct udevice_id button_gpio_ids[] = {

View file

@ -38,6 +38,16 @@ enum button_state_t button_get_state(struct udevice *dev)
return ops->get_state(dev); return ops->get_state(dev);
} }
int button_get_code(struct udevice *dev)
{
struct button_ops *ops = button_get_ops(dev);
if (!ops->get_code)
return -ENOSYS;
return ops->get_code(dev);
}
UCLASS_DRIVER(button) = { UCLASS_DRIVER(button) = {
.id = UCLASS_BUTTON, .id = UCLASS_BUTTON,
.name = "button", .name = "button",

View file

@ -303,9 +303,25 @@ static int qcom_pwrkey_get_value(struct udevice *dev, unsigned offset)
} }
} }
/*
* Since pmic buttons modelled as GPIO, we need empty direction functions
* to trick u-boot button driver
*/
static int qcom_pwrkey_direction_input(struct udevice *dev, unsigned int offset)
{
return 0;
}
static int qcom_pwrkey_direction_output(struct udevice *dev, unsigned int offset, int value)
{
return -EOPNOTSUPP;
}
static const struct dm_gpio_ops qcom_pwrkey_ops = { static const struct dm_gpio_ops qcom_pwrkey_ops = {
.get_value = qcom_pwrkey_get_value, .get_value = qcom_pwrkey_get_value,
.get_function = qcom_pwrkey_get_function, .get_function = qcom_pwrkey_get_function,
.direction_input = qcom_pwrkey_direction_input,
.direction_output = qcom_pwrkey_direction_output,
}; };
static int qcom_pwrkey_probe(struct udevice *dev) static int qcom_pwrkey_probe(struct udevice *dev)

View file

@ -580,6 +580,18 @@ config SYS_I2C_OCTEON
chips have several I2C ports and all are provided, controlled by chips have several I2C ports and all are provided, controlled by
the device tree. the device tree.
config SYS_I2C_QUP
bool "Qualcomm QUP I2C controller"
depends on ARCH_SNAPDRAGON
help
Support for Qualcomm QUP I2C controller based on Qualcomm Universal
Peripherals (QUP) engine. The QUP engine is an advanced high
performance slave port that provides a common data path (an output
FIFO and an input FIFO) for I2C and SPI interfaces. The I2C/SPI QUP
controller is publicly documented in the Snapdragon 410E (APQ8016E)
Technical Reference Manual, chapter "6.1 Qualcomm Universal
Peripherals Engine (QUP)".
config SYS_I2C_S3C24X0 config SYS_I2C_S3C24X0
bool "Samsung I2C driver" bool "Samsung I2C driver"
depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5) && DM_I2C depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5) && DM_I2C

View file

@ -37,6 +37,7 @@ obj-$(CONFIG_SYS_I2C_NPCM) += npcm_i2c.o
obj-$(CONFIG_SYS_I2C_OCORES) += ocores_i2c.o obj-$(CONFIG_SYS_I2C_OCORES) += ocores_i2c.o
obj-$(CONFIG_SYS_I2C_OCTEON) += octeon_i2c.o obj-$(CONFIG_SYS_I2C_OCTEON) += octeon_i2c.o
obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o
obj-$(CONFIG_SYS_I2C_QUP) += qup_i2c.o
obj-$(CONFIG_SYS_I2C_RCAR_I2C) += rcar_i2c.o obj-$(CONFIG_SYS_I2C_RCAR_I2C) += rcar_i2c.o
obj-$(CONFIG_SYS_I2C_RCAR_IIC) += rcar_iic.o obj-$(CONFIG_SYS_I2C_RCAR_IIC) += rcar_iic.o
obj-$(CONFIG_SYS_I2C_ROCKCHIP) += rk_i2c.o obj-$(CONFIG_SYS_I2C_ROCKCHIP) += rk_i2c.o

579
drivers/i2c/qup_i2c.c Normal file
View file

@ -0,0 +1,579 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2009-2013, 2016-2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2014, Sony Mobile Communications AB.
* Copyright (c) 2022-2023, Sumit Garg <sumit.garg@linaro.org>
*
* Inspired by corresponding driver in Linux: drivers/i2c/busses/i2c-qup.c
*/
#include <init.h>
#include <env.h>
#include <common.h>
#include <log.h>
#include <dm/device_compat.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/compat.h>
#include <linux/bitops.h>
#include <asm/io.h>
#include <i2c.h>
#include <watchdog.h>
#include <fdtdec.h>
#include <clk.h>
#include <reset.h>
#include <asm/arch/gpio.h>
#include <cpu_func.h>
#include <asm/system.h>
#include <asm/gpio.h>
#include <dm.h>
#include <dm/pinctrl.h>
/* QUP Registers */
#define QUP_CONFIG 0x000
#define QUP_STATE 0x004
#define QUP_IO_MODE 0x008
#define QUP_SW_RESET 0x00c
#define QUP_OPERATIONAL 0x018
#define QUP_ERROR_FLAGS 0x01c /* NOT USED */
#define QUP_ERROR_FLAGS_EN 0x020 /* NOT USED */
#define QUP_TEST_CTRL 0x024 /* NOT USED */
#define QUP_OPERATIONAL_MASK 0x028 /* NOT USED */
#define QUP_HW_VERSION 0x030
#define QUP_MX_OUTPUT_CNT 0x100
#define QUP_OUT_DEBUG 0x108 /* NOT USED */
#define QUP_OUT_FIFO_CNT 0x10C /* NOT USED */
#define QUP_OUT_FIFO_BASE 0x110
#define QUP_MX_WRITE_CNT 0x150
#define QUP_MX_INPUT_CNT 0x200
#define QUP_MX_READ_CNT 0x208
#define QUP_IN_READ_CUR 0x20C /* NOT USED */
#define QUP_IN_DEBUG 0x210 /* NOT USED */
#define QUP_IN_FIFO_CNT 0x214 /* NOT USED */
#define QUP_IN_FIFO_BASE 0x218
#define QUP_I2C_CLK_CTL 0x400
#define QUP_I2C_STATUS 0x404 /* NOT USED */
#define QUP_I2C_MASTER_GEN 0x408
#define QUP_I2C_MASTER_BUS_CLR 0x40C /* NOT USED */
/* QUP States and reset values */
#define QUP_RESET_STATE 0
#define QUP_RUN_STATE 1
#define QUP_PAUSE_STATE 3
#define QUP_STATE_MASK 3
#define QUP_STATE_VALID BIT(2)
#define QUP_I2C_MAST_GEN BIT(4)
#define QUP_I2C_FLUSH BIT(6)
#define QUP_OPERATIONAL_RESET 0x000ff0
#define QUP_I2C_STATUS_RESET 0xfffffc
/* QUP OPERATIONAL FLAGS */
#define QUP_I2C_NACK_FLAG BIT(3)
#define QUP_OUT_NOT_EMPTY BIT(4)
#define QUP_IN_NOT_EMPTY BIT(5)
#define QUP_OUT_FULL BIT(6)
#define QUP_OUT_SVC_FLAG BIT(8)
#define QUP_IN_SVC_FLAG BIT(9)
#define QUP_MX_OUTPUT_DONE BIT(10)
#define QUP_MX_INPUT_DONE BIT(11)
#define OUT_BLOCK_WRITE_REQ BIT(12)
#define IN_BLOCK_READ_REQ BIT(13)
/*
* QUP engine acting as I2C controller is referred to as
* I2C mini core, following are related macros.
*/
#define QUP_NO_OUTPUT BIT(6)
#define QUP_NO_INPUT BIT(7)
#define QUP_CLOCK_AUTO_GATE BIT(13)
#define QUP_I2C_MINI_CORE (2 << 8)
#define QUP_I2C_N_VAL_V2 7
/* Packing/Unpacking words in FIFOs, and IO modes */
#define QUP_OUTPUT_BLK_MODE BIT(10)
#define QUP_OUTPUT_BAM_MODE (BIT(10) | BIT(11))
#define QUP_INPUT_BLK_MODE BIT(12)
#define QUP_INPUT_BAM_MODE (BIT(12) | BIT(13))
#define QUP_BAM_MODE (QUP_OUTPUT_BAM_MODE | QUP_INPUT_BAM_MODE)
#define QUP_BLK_MODE (QUP_OUTPUT_BLK_MODE | QUP_INPUT_BLK_MODE)
#define QUP_UNPACK_EN BIT(14)
#define QUP_PACK_EN BIT(15)
#define QUP_REPACK_EN (QUP_UNPACK_EN | QUP_PACK_EN)
#define QUP_V2_TAGS_EN 1
#define QUP_OUTPUT_BLOCK_SIZE(x) (((x) >> 0) & 0x03)
#define QUP_OUTPUT_FIFO_SIZE(x) (((x) >> 2) & 0x07)
#define QUP_INPUT_BLOCK_SIZE(x) (((x) >> 5) & 0x03)
#define QUP_INPUT_FIFO_SIZE(x) (((x) >> 7) & 0x07)
/* QUP v2 tags */
#define QUP_TAG_V2_START 0x81
#define QUP_TAG_V2_DATAWR 0x82
#define QUP_TAG_V2_DATAWR_STOP 0x83
#define QUP_TAG_V2_DATARD 0x85
#define QUP_TAG_V2_DATARD_NACK 0x86
#define QUP_TAG_V2_DATARD_STOP 0x87
#define QUP_I2C_MX_CONFIG_DURING_RUN BIT(31)
/* Minimum transfer timeout for i2c transfers in micro seconds */
#define TOUT_CNT (2 * 1000 * 1000)
/* Default values. Use these if FW query fails */
#define DEFAULT_CLK_FREQ I2C_SPEED_STANDARD_RATE
#define DEFAULT_SRC_CLK 19200000
/*
* Max tags length (start, stop and maximum 2 bytes address) for each QUP
* data transfer
*/
#define QUP_MAX_TAGS_LEN 4
/* Max data length for each DATARD tags */
#define RECV_MAX_DATA_LEN 254
/* TAG length for DATA READ in RX FIFO */
#define READ_RX_TAGS_LEN 2
struct qup_i2c_priv {
phys_addr_t base;
struct clk core;
struct clk iface;
u32 in_fifo_sz;
u32 out_fifo_sz;
u32 clk_ctl;
u32 config_run;
};
static inline u8 i2c_8bit_addr_from_msg(const struct i2c_msg *msg)
{
return (msg->addr << 1) | (msg->flags & I2C_M_RD ? 1 : 0);
}
static int qup_i2c_poll_state_mask(struct qup_i2c_priv *qup,
u32 req_state, u32 req_mask)
{
int retries = 1;
u32 state;
/*
* State transition takes 3 AHB clocks cycles + 3 I2C master clock
* cycles. So retry once after a 1uS delay.
*/
do {
state = readl(qup->base + QUP_STATE);
if (state & QUP_STATE_VALID &&
(state & req_mask) == req_state)
return 0;
udelay(1);
} while (retries--);
return -ETIMEDOUT;
}
static int qup_i2c_poll_state(struct qup_i2c_priv *qup, u32 req_state)
{
return qup_i2c_poll_state_mask(qup, req_state, QUP_STATE_MASK);
}
static int qup_i2c_poll_state_valid(struct qup_i2c_priv *qup)
{
return qup_i2c_poll_state_mask(qup, 0, 0);
}
static int qup_i2c_poll_state_i2c_master(struct qup_i2c_priv *qup)
{
return qup_i2c_poll_state_mask(qup, QUP_I2C_MAST_GEN, QUP_I2C_MAST_GEN);
}
static int qup_i2c_change_state(struct qup_i2c_priv *qup, u32 state)
{
if (qup_i2c_poll_state_valid(qup) != 0)
return -EIO;
writel(state, qup->base + QUP_STATE);
if (qup_i2c_poll_state(qup, state) != 0)
return -EIO;
return 0;
}
/*
* Function to check wheather Input or Output FIFO
* has data to be serviced
*/
static int qup_i2c_check_fifo_status(struct qup_i2c_priv *qup, u32 reg_addr,
u32 flags)
{
unsigned long count = TOUT_CNT;
u32 val, status_flag;
int ret = 0;
do {
val = readl(qup->base + reg_addr);
status_flag = val & flags;
if (!count) {
printf("%s, timeout\n", __func__);
ret = -ETIMEDOUT;
break;
}
count--;
udelay(1);
} while (!status_flag);
return ret;
}
/*
* Function to configure Input and Output enable/disable
*/
static void qup_i2c_enable_io_config(struct qup_i2c_priv *qup, u32 write_cnt,
u32 read_cnt)
{
u32 qup_config = QUP_I2C_MINI_CORE | QUP_I2C_N_VAL_V2;
writel(qup->config_run | write_cnt, qup->base + QUP_MX_WRITE_CNT);
if (read_cnt)
writel(qup->config_run | read_cnt, qup->base + QUP_MX_READ_CNT);
else
qup_config |= QUP_NO_INPUT;
writel(qup_config, qup->base + QUP_CONFIG);
}
static unsigned int qup_i2c_read_word(struct qup_i2c_priv *qup)
{
return readl(qup->base + QUP_IN_FIFO_BASE);
}
static void qup_i2c_write_word(struct qup_i2c_priv *qup, u32 word)
{
writel(word, qup->base + QUP_OUT_FIFO_BASE);
}
static int qup_i2c_blsp_read(struct qup_i2c_priv *qup, unsigned int addr,
bool last, u8 *buffer, unsigned int bytes)
{
unsigned int i, j, word;
int ret = 0;
/* FIFO mode size limitation, for larger size implement block mode */
if (bytes > (qup->in_fifo_sz - READ_RX_TAGS_LEN))
return -EINVAL;
qup_i2c_enable_io_config(qup, QUP_MAX_TAGS_LEN,
bytes + READ_RX_TAGS_LEN);
if (last)
qup_i2c_write_word(qup, QUP_TAG_V2_START | addr << 8 |
QUP_TAG_V2_DATARD_STOP << 16 |
bytes << 24);
else
qup_i2c_write_word(qup, QUP_TAG_V2_START | addr << 8 |
QUP_TAG_V2_DATARD << 16 | bytes << 24);
ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
if (ret)
return ret;
ret = qup_i2c_check_fifo_status(qup, QUP_OPERATIONAL, QUP_OUT_SVC_FLAG);
if (ret)
return ret;
writel(QUP_OUT_SVC_FLAG, qup->base + QUP_OPERATIONAL);
ret = qup_i2c_check_fifo_status(qup, QUP_OPERATIONAL, QUP_IN_SVC_FLAG);
if (ret)
return ret;
writel(QUP_IN_SVC_FLAG, qup->base + QUP_OPERATIONAL);
word = qup_i2c_read_word(qup);
*(buffer++) = (word >> (8 * READ_RX_TAGS_LEN)) & 0xff;
if (bytes > 1)
*(buffer++) = (word >> (8 * (READ_RX_TAGS_LEN + 1))) & 0xff;
for (i = 2; i < bytes; i += 4) {
word = qup_i2c_read_word(qup);
for (j = 0; j < 4; j++) {
if ((i + j) == bytes)
break;
*buffer = (word >> (j * 8)) & 0xff;
buffer++;
}
}
ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
return ret;
}
static int qup_i2c_blsp_write(struct qup_i2c_priv *qup, unsigned int addr,
bool first, bool last, const u8 *buffer,
unsigned int bytes)
{
unsigned int i;
u32 word = 0;
int ret = 0;
/* FIFO mode size limitation, for larger size implement block mode */
if (bytes > (qup->out_fifo_sz - QUP_MAX_TAGS_LEN))
return -EINVAL;
qup_i2c_enable_io_config(qup, bytes + QUP_MAX_TAGS_LEN, 0);
if (first) {
ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
if (ret)
return ret;
writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
if (ret)
return ret;
}
if (last)
qup_i2c_write_word(qup, QUP_TAG_V2_START | addr << 8 |
QUP_TAG_V2_DATAWR_STOP << 16 |
bytes << 24);
else
qup_i2c_write_word(qup, QUP_TAG_V2_START | addr << 8 |
QUP_TAG_V2_DATAWR << 16 | bytes << 24);
for (i = 0; i < bytes; i++) {
/* Write the byte of data */
word |= *buffer << ((i % 4) * 8);
if ((i % 4) == 3) {
qup_i2c_write_word(qup, word);
word = 0;
}
buffer++;
}
if ((i % 4) != 0)
qup_i2c_write_word(qup, word);
ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
if (ret)
return ret;
ret = qup_i2c_check_fifo_status(qup, QUP_OPERATIONAL, QUP_OUT_SVC_FLAG);
if (ret)
return ret;
writel(QUP_OUT_SVC_FLAG, qup->base + QUP_OPERATIONAL);
ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
return ret;
}
static void qup_i2c_conf_mode_v2(struct qup_i2c_priv *qup)
{
u32 io_mode = QUP_REPACK_EN;
writel(0, qup->base + QUP_MX_OUTPUT_CNT);
writel(0, qup->base + QUP_MX_INPUT_CNT);
writel(io_mode, qup->base + QUP_IO_MODE);
}
static int qup_i2c_xfer_v2(struct udevice *bus, struct i2c_msg msgs[], int num)
{
struct qup_i2c_priv *qup = dev_get_priv(bus);
int ret, idx = 0;
u32 i2c_addr;
writel(1, qup->base + QUP_SW_RESET);
ret = qup_i2c_poll_state(qup, QUP_RESET_STATE);
if (ret)
goto out;
/* Configure QUP as I2C mini core */
writel(QUP_I2C_MINI_CORE | QUP_I2C_N_VAL_V2 | QUP_NO_INPUT,
qup->base + QUP_CONFIG);
writel(QUP_V2_TAGS_EN, qup->base + QUP_I2C_MASTER_GEN);
if (qup_i2c_poll_state_i2c_master(qup)) {
ret = -EIO;
goto out;
}
qup_i2c_conf_mode_v2(qup);
for (idx = 0; idx < num; idx++) {
struct i2c_msg *m = &msgs[idx];
qup->config_run = !idx ? 0 : QUP_I2C_MX_CONFIG_DURING_RUN;
i2c_addr = i2c_8bit_addr_from_msg(m);
if (m->flags & I2C_M_RD)
ret = qup_i2c_blsp_read(qup, i2c_addr, idx == (num - 1),
m->buf, m->len);
else
ret = qup_i2c_blsp_write(qup, i2c_addr, idx == 0,
idx == (num - 1), m->buf,
m->len);
if (ret)
break;
}
out:
qup_i2c_change_state(qup, QUP_RESET_STATE);
return ret;
}
static int qup_i2c_enable_clocks(struct udevice *dev, struct qup_i2c_priv *qup)
{
int ret;
ret = clk_enable(&qup->core);
if (ret) {
dev_err(dev, "clk_enable failed %d\n", ret);
return ret;
}
ret = clk_enable(&qup->iface);
if (ret) {
dev_err(dev, "clk_enable failed %d\n", ret);
return ret;
}
return 0;
}
static int qup_i2c_probe(struct udevice *dev)
{
static const int blk_sizes[] = {4, 16, 32};
struct qup_i2c_priv *qup = dev_get_priv(dev);
u32 io_mode, hw_ver, size, size_idx;
int ret;
qup->base = (phys_addr_t)dev_read_addr_ptr(dev);
if (!qup->base)
return -EINVAL;
ret = clk_get_by_name(dev, "core", &qup->core);
if (ret) {
pr_err("clk_get_by_name(core) failed: %d\n", ret);
return ret;
}
ret = clk_get_by_name(dev, "iface", &qup->iface);
if (ret) {
pr_err("clk_get_by_name(iface) failed: %d\n", ret);
return ret;
}
qup_i2c_enable_clocks(dev, qup);
writel(1, qup->base + QUP_SW_RESET);
ret = qup_i2c_poll_state_valid(qup);
if (ret)
return ret;
hw_ver = readl(qup->base + QUP_HW_VERSION);
dev_dbg(dev, "Revision %x\n", hw_ver);
io_mode = readl(qup->base + QUP_IO_MODE);
/*
* The block/fifo size w.r.t. 'actual data' is 1/2 due to 'tag'
* associated with each byte written/received
*/
size_idx = QUP_OUTPUT_BLOCK_SIZE(io_mode);
if (size_idx >= ARRAY_SIZE(blk_sizes)) {
ret = -EIO;
return ret;
}
size = QUP_OUTPUT_FIFO_SIZE(io_mode);
qup->out_fifo_sz = blk_sizes[size_idx] * (2 << size);
size_idx = QUP_INPUT_BLOCK_SIZE(io_mode);
if (size_idx >= ARRAY_SIZE(blk_sizes)) {
ret = -EIO;
return ret;
}
size = QUP_INPUT_FIFO_SIZE(io_mode);
qup->in_fifo_sz = blk_sizes[size_idx] * (2 << size);
dev_dbg(dev, "IN:fifo:%d, OUT:fifo:%d\n", qup->in_fifo_sz,
qup->out_fifo_sz);
return 0;
}
static int qup_i2c_set_bus_speed(struct udevice *dev, unsigned int clk_freq)
{
struct qup_i2c_priv *qup = dev_get_priv(dev);
unsigned int src_clk_freq;
int fs_div, hs_div;
/* We support frequencies up to FAST Mode Plus (1MHz) */
if (!clk_freq || clk_freq > I2C_SPEED_FAST_PLUS_RATE) {
dev_err(dev, "clock frequency not supported %d\n", clk_freq);
return -EINVAL;
}
src_clk_freq = clk_get_rate(&qup->iface);
if ((int)src_clk_freq < 0) {
src_clk_freq = DEFAULT_SRC_CLK;
dev_dbg(dev, "using default core freq %d\n", src_clk_freq);
}
dev_dbg(dev, "src_clk_freq %u\n", src_clk_freq);
dev_dbg(dev, "clk_freq %u\n", clk_freq);
hs_div = 3;
if (clk_freq <= I2C_SPEED_STANDARD_RATE) {
fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff);
} else {
/* 33%/66% duty cycle */
fs_div = ((src_clk_freq / clk_freq) - 6) * 2 / 3;
qup->clk_ctl = ((fs_div / 2) << 16) | (hs_div << 8) | (fs_div & 0xff);
}
dev_dbg(dev, "clk_ctl %u\n", qup->clk_ctl);
return 0;
}
/* Probe to see if a chip is present. */
static int qup_i2c_probe_chip(struct udevice *dev, uint chip_addr,
uint chip_flags)
{
struct qup_i2c_priv *qup = dev_get_priv(dev);
u32 hw_ver = readl(qup->base + QUP_HW_VERSION);
return hw_ver ? 0 : -1;
}
static const struct dm_i2c_ops qup_i2c_ops = {
.xfer = qup_i2c_xfer_v2,
.probe_chip = qup_i2c_probe_chip,
.set_bus_speed = qup_i2c_set_bus_speed,
};
/*
* Currently this driver only supports v2.x of QUP I2C controller, hence
* functions above are named with a _v2 suffix. So when we have the
* v1.1.1 support added as per the Linux counterpart then it should be easy
* to add corresponding functions named with a _v1 suffix.
*/
static const struct udevice_id qup_i2c_ids[] = {
{ .compatible = "qcom,i2c-qup-v2.1.1" },
{ .compatible = "qcom,i2c-qup-v2.2.1" },
{}
};
U_BOOT_DRIVER(i2c_qup) = {
.name = "i2c_qup",
.id = UCLASS_I2C,
.of_match = qup_i2c_ids,
.probe = qup_i2c_probe,
.priv_auto = sizeof(struct qup_i2c_priv),
.ops = &qup_i2c_ops,
};

View file

@ -46,6 +46,15 @@ config APPLE_SPI_KEYB
laptops based on Apple SoCs. These keyboards use an laptops based on Apple SoCs. These keyboards use an
Apple-specific HID-over-SPI protocol. Apple-specific HID-over-SPI protocol.
config BUTTON_KEYBOARD
bool "Buttons as keyboard"
depends on BUTTON_GPIO
depends on DM_KEYBOARD
help
Enable support for mapping buttons to keycode events. Use linux,code button driver
dt node to define button-event mapping.
For example, an arrows and enter may be implemented to navigate boot menu.
config CROS_EC_KEYB config CROS_EC_KEYB
bool "Enable Chrome OS EC keyboard support" bool "Enable Chrome OS EC keyboard support"
depends on INPUT depends on INPUT

View file

@ -6,6 +6,7 @@
obj-$(CONFIG_$(SPL_TPL_)CROS_EC_KEYB) += cros_ec_keyb.o obj-$(CONFIG_$(SPL_TPL_)CROS_EC_KEYB) += cros_ec_keyb.o
obj-$(CONFIG_$(SPL_TPL_)OF_CONTROL) += key_matrix.o obj-$(CONFIG_$(SPL_TPL_)OF_CONTROL) += key_matrix.o
obj-$(CONFIG_$(SPL_TPL_)DM_KEYBOARD) += input.o keyboard-uclass.o obj-$(CONFIG_$(SPL_TPL_)DM_KEYBOARD) += input.o keyboard-uclass.o
obj-$(CONFIG_BUTTON_KEYBOARD) += button_kbd.o
ifndef CONFIG_SPL_BUILD ifndef CONFIG_SPL_BUILD

126
drivers/input/button_kbd.c Normal file
View file

@ -0,0 +1,126 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2023 Dzmitry Sankouski <dsankouski@gmail.com>
*/
#include <stdlib.h>
#include <common.h>
#include <dm.h>
#include <fdtdec.h>
#include <input.h>
#include <keyboard.h>
#include <button.h>
#include <dm/device-internal.h>
#include <log.h>
#include <asm/io.h>
#include <asm/gpio.h>
#include <linux/delay.h>
#include <linux/input.h>
/**
* struct button_kbd_priv - driver private data
*
* @input: input configuration
* @button_size: number of buttons found
* @old_state: a pointer to old button states array. Used to determine button state change.
*/
struct button_kbd_priv {
struct input_config *input;
u32 button_size;
u32 *old_state;
};
static int button_kbd_start(struct udevice *dev)
{
struct button_kbd_priv *priv = dev_get_priv(dev);
int i = 0;
struct udevice *button_gpio_devp;
uclass_foreach_dev_probe(UCLASS_BUTTON, button_gpio_devp) {
struct button_uc_plat *uc_plat = dev_get_uclass_plat(button_gpio_devp);
/* Ignore the top-level button node */
if (!uc_plat->label)
continue;
debug("Found button %s #%d - %s, probing...\n",
uc_plat->label, i, button_gpio_devp->name);
i++;
}
priv->button_size = i;
priv->old_state = calloc(i, sizeof(int));
return 0;
}
int button_read_keys(struct input_config *input)
{
struct button_kbd_priv *priv = dev_get_priv(input->dev);
struct udevice *button_gpio_devp;
struct uclass *uc;
int i = 0;
u32 code, state, state_changed = 0;
uclass_id_foreach_dev(UCLASS_BUTTON, button_gpio_devp, uc) {
struct button_uc_plat *uc_plat = dev_get_uclass_plat(button_gpio_devp);
/* Ignore the top-level button node */
if (!uc_plat->label)
continue;
code = button_get_code(button_gpio_devp);
if (!code)
continue;
state = button_get_state(button_gpio_devp);
state_changed = state != priv->old_state[i];
if (state_changed) {
debug("%s: %d\n", uc_plat->label, code);
priv->old_state[i] = state;
input_add_keycode(input, code, state);
}
i++;
}
return 0;
}
static const struct keyboard_ops button_kbd_ops = {
.start = button_kbd_start,
};
static int button_kbd_probe(struct udevice *dev)
{
struct button_kbd_priv *priv = dev_get_priv(dev);
struct keyboard_priv *uc_priv = dev_get_uclass_priv(dev);
struct stdio_dev *sdev = &uc_priv->sdev;
struct input_config *input = &uc_priv->input;
int ret = 0;
input_init(input, false);
input_add_tables(input, false);
/* Register the device. */
priv->input = input;
input->dev = dev;
input->read_keys = button_read_keys;
strcpy(sdev->name, "button-kbd");
ret = input_stdio_register(sdev);
if (ret) {
debug("%s: input_stdio_register() failed\n", __func__);
return ret;
}
return 0;
}
static const struct udevice_id button_kbd_ids[] = {
{ .compatible = "button-kbd" },
{ }
};
U_BOOT_DRIVER(button_kbd) = {
.name = "button_kbd",
.id = UCLASS_KEYBOARD,
.of_match = button_kbd_ids,
.ops = &button_kbd_ops,
.priv_auto = sizeof(struct button_kbd_priv),
.probe = button_kbd_probe,
};

View file

@ -242,6 +242,13 @@ config DWC_ETH_QOS_TEGRA186
The Synopsys Designware Ethernet QOS IP block with specific The Synopsys Designware Ethernet QOS IP block with specific
configuration used in NVIDIA's Tegra186 chip. configuration used in NVIDIA's Tegra186 chip.
config DWC_ETH_QOS_QCOM
bool "Synopsys DWC Ethernet QOS device support for Qcom SoCs"
depends on DWC_ETH_QOS
help
The Synopsys Designware Ethernet QOS IP block with specific
configuration used in Qcom QCS404 SoC.
config E1000 config E1000
bool "Intel PRO/1000 Gigabit Ethernet support" bool "Intel PRO/1000 Gigabit Ethernet support"
depends on PCI depends on PCI
@ -406,6 +413,7 @@ config FSL_FM_10GEC_REGULAR_NOTATION
config FTMAC100 config FTMAC100
bool "Ftmac100 Ethernet Support" bool "Ftmac100 Ethernet Support"
select MII
help help
This MAC is present in Andestech SoCs. This MAC is present in Andestech SoCs.

View file

@ -20,6 +20,7 @@ obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o
obj-$(CONFIG_DSA_SANDBOX) += dsa_sandbox.o obj-$(CONFIG_DSA_SANDBOX) += dsa_sandbox.o
obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o
obj-$(CONFIG_DWC_ETH_QOS_IMX) += dwc_eth_qos_imx.o obj-$(CONFIG_DWC_ETH_QOS_IMX) += dwc_eth_qos_imx.o
obj-$(CONFIG_DWC_ETH_QOS_QCOM) += dwc_eth_qos_qcom.o
obj-$(CONFIG_E1000) += e1000.o obj-$(CONFIG_E1000) += e1000.o
obj-$(CONFIG_E1000_SPI) += e1000_spi.o obj-$(CONFIG_E1000_SPI) += e1000_spi.o
obj-$(CONFIG_EEPRO100) += eepro100.o obj-$(CONFIG_EEPRO100) += eepro100.o

View file

@ -774,10 +774,13 @@ static int eqos_start(struct udevice *dev)
pr_err("eqos_calibrate_pads() failed: %d", ret); pr_err("eqos_calibrate_pads() failed: %d", ret);
goto err_stop_resets; goto err_stop_resets;
} }
rate = eqos->config->ops->eqos_get_tick_clk_rate(dev);
val = (rate / 1000000) - 1; if (eqos->config->ops->eqos_get_tick_clk_rate) {
writel(val, &eqos->mac_regs->us_tic_counter); rate = eqos->config->ops->eqos_get_tick_clk_rate(dev);
val = (rate / 1000000) - 1;
writel(val, &eqos->mac_regs->us_tic_counter);
}
/* /*
* if PHY was already connected and configured, * if PHY was already connected and configured,
@ -849,12 +852,19 @@ static int eqos_start(struct udevice *dev)
rx_fifo_sz = (val >> EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_SHIFT) & rx_fifo_sz = (val >> EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_SHIFT) &
EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_MASK; EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_MASK;
/* /* r/tx_fifo_sz is encoded as log2(n / 128). Undo that by shifting */
* r/tx_fifo_sz is encoded as log2(n / 128). Undo that by shifting. tx_fifo_sz = 128 << tx_fifo_sz;
* r/tqs is encoded as (n / 256) - 1. rx_fifo_sz = 128 << rx_fifo_sz;
*/
tqs = (128 << tx_fifo_sz) / 256 - 1; /* Allow platform to override TX/RX fifo size */
rqs = (128 << rx_fifo_sz) / 256 - 1; if (eqos->tx_fifo_sz)
tx_fifo_sz = eqos->tx_fifo_sz;
if (eqos->rx_fifo_sz)
rx_fifo_sz = eqos->rx_fifo_sz;
/* r/tqs is encoded as (n / 256) - 1 */
tqs = tx_fifo_sz / 256 - 1;
rqs = rx_fifo_sz / 256 - 1;
clrsetbits_le32(&eqos->mtl_regs->txq0_operation_mode, clrsetbits_le32(&eqos->mtl_regs->txq0_operation_mode,
EQOS_MTL_TXQ0_OPERATION_MODE_TQS_MASK << EQOS_MTL_TXQ0_OPERATION_MODE_TQS_MASK <<
@ -1702,6 +1712,13 @@ static const struct udevice_id eqos_ids[] = {
}, },
#endif #endif
#if IS_ENABLED(CONFIG_DWC_ETH_QOS_QCOM)
{
.compatible = "qcom,qcs404-ethqos",
.data = (ulong)&eqos_qcom_config
},
#endif
{ } { }
}; };

View file

@ -253,6 +253,7 @@ struct eqos_priv {
struct eqos_mtl_regs *mtl_regs; struct eqos_mtl_regs *mtl_regs;
struct eqos_dma_regs *dma_regs; struct eqos_dma_regs *dma_regs;
struct eqos_tegra186_regs *tegra186_regs; struct eqos_tegra186_regs *tegra186_regs;
void *eqos_qcom_rgmii_regs;
struct reset_ctl reset_ctl; struct reset_ctl reset_ctl;
struct gpio_desc phy_reset_gpio; struct gpio_desc phy_reset_gpio;
struct clk clk_master_bus; struct clk clk_master_bus;
@ -276,6 +277,8 @@ struct eqos_priv {
bool started; bool started;
bool reg_access_ok; bool reg_access_ok;
bool clk_ck_enabled; bool clk_ck_enabled;
unsigned int tx_fifo_sz, rx_fifo_sz;
u32 reset_delays[3];
}; };
void eqos_inval_desc_generic(void *desc); void eqos_inval_desc_generic(void *desc);
@ -285,3 +288,4 @@ void eqos_flush_buffer_generic(void *buf, size_t size);
int eqos_null_ops(struct udevice *dev); int eqos_null_ops(struct udevice *dev);
extern struct eqos_config eqos_imx_config; extern struct eqos_config eqos_imx_config;
extern struct eqos_config eqos_qcom_config;

View file

@ -0,0 +1,612 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2022-2023 Sumit Garg <sumit.garg@linaro.org>
*
* Qcom DWMAC specific glue layer
*/
#include <common.h>
#include <asm/global_data.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <clk.h>
#include <dm.h>
#include <dm/device_compat.h>
#include <phy.h>
#include <reset.h>
#include <syscon.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include "dwc_eth_qos.h"
/* RGMII_IO_MACRO_CONFIG fields */
#define RGMII_CONFIG_FUNC_CLK_EN BIT(30)
#define RGMII_CONFIG_POS_NEG_DATA_SEL BIT(23)
#define RGMII_CONFIG_GPIO_CFG_RX_INT GENMASK(21, 20)
#define RGMII_CONFIG_GPIO_CFG_TX_INT GENMASK(19, 17)
#define RGMII_CONFIG_MAX_SPD_PRG_9 GENMASK(16, 8)
#define RGMII_CONFIG_MAX_SPD_PRG_2 GENMASK(7, 6)
#define RGMII_CONFIG_INTF_SEL GENMASK(5, 4)
#define RGMII_CONFIG_BYPASS_TX_ID_EN BIT(3)
#define RGMII_CONFIG_LOOPBACK_EN BIT(2)
#define RGMII_CONFIG_PROG_SWAP BIT(1)
#define RGMII_CONFIG_DDR_MODE BIT(0)
/* SDCC_HC_REG_DLL_CONFIG fields */
#define SDCC_DLL_CONFIG_DLL_RST BIT(30)
#define SDCC_DLL_CONFIG_PDN BIT(29)
#define SDCC_DLL_CONFIG_MCLK_FREQ GENMASK(26, 24)
#define SDCC_DLL_CONFIG_CDR_SELEXT GENMASK(23, 20)
#define SDCC_DLL_CONFIG_CDR_EXT_EN BIT(19)
#define SDCC_DLL_CONFIG_CK_OUT_EN BIT(18)
#define SDCC_DLL_CONFIG_CDR_EN BIT(17)
#define SDCC_DLL_CONFIG_DLL_EN BIT(16)
#define SDCC_DLL_MCLK_GATING_EN BIT(5)
#define SDCC_DLL_CDR_FINE_PHASE GENMASK(3, 2)
/* SDCC_HC_REG_DDR_CONFIG fields */
#define SDCC_DDR_CONFIG_PRG_DLY_EN BIT(31)
#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY GENMASK(26, 21)
#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE GENMASK(29, 27)
#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN BIT(30)
#define SDCC_DDR_CONFIG_PRG_RCLK_DLY GENMASK(8, 0)
/* SDCC_HC_REG_DLL_CONFIG2 fields */
#define SDCC_DLL_CONFIG2_DLL_CLOCK_DIS BIT(21)
#define SDCC_DLL_CONFIG2_MCLK_FREQ_CALC GENMASK(17, 10)
#define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL GENMASK(3, 2)
#define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW BIT(1)
#define SDCC_DLL_CONFIG2_DDR_CAL_EN BIT(0)
/* SDC4_STATUS bits */
#define SDC4_STATUS_DLL_LOCK BIT(7)
/* RGMII_IO_MACRO_CONFIG2 fields */
#define RGMII_CONFIG2_RSVD_CONFIG15 GENMASK(31, 17)
#define RGMII_CONFIG2_RGMII_CLK_SEL_CFG BIT(16)
#define RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN BIT(13)
#define RGMII_CONFIG2_CLK_DIVIDE_SEL BIT(12)
#define RGMII_CONFIG2_RX_PROG_SWAP BIT(7)
#define RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL BIT(6)
#define RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN BIT(5)
struct dwmac_rgmii_regs {
u32 io_macro_config; /* 0x00 */
u32 sdcc_hc_dll_config; /* 0x04 */
u32 reserved_1; /* 0x08 */
u32 sdcc_hc_ddr_config; /* 0x0c */
u32 sdcc_hc_dll_config2; /* 0x10 */
u32 sdc4_status; /* 0x14 */
u32 sdcc_usr_ctl; /* 0x18 */
u32 io_macro_config2; /* 0x1c */
u32 io_macro_debug1; /* 0x20 */
u32 reserved_2; /* 0x24 */
u32 emac_sys_low_power_dbg; /* 0x28 */
u32 reserved_3[53]; /* upto 0x100 */
};
static struct dwmac_rgmii_regs emac_v2_3_0_por = {
.io_macro_config = 0x00C01343,
.sdcc_hc_dll_config = 0x2004642C,
.sdcc_hc_ddr_config = 0x00000000,
.sdcc_hc_dll_config2 = 0x00200000,
.sdcc_usr_ctl = 0x00010800,
.io_macro_config2 = 0x00002060
};
static void ethqos_set_func_clk_en(struct dwmac_rgmii_regs *regs)
{
setbits_le32(&regs->io_macro_config, RGMII_CONFIG_FUNC_CLK_EN);
}
static int ethqos_dll_configure(struct udevice *dev,
struct dwmac_rgmii_regs *regs)
{
unsigned int val;
int retry = 1000;
/* Set CDR_EN */
setbits_le32(&regs->sdcc_hc_dll_config, SDCC_DLL_CONFIG_CDR_EN);
/* Set CDR_EXT_EN */
setbits_le32(&regs->sdcc_hc_dll_config, SDCC_DLL_CONFIG_CDR_EXT_EN);
/* Clear CK_OUT_EN */
clrbits_le32(&regs->sdcc_hc_dll_config, SDCC_DLL_CONFIG_CK_OUT_EN);
/* Set DLL_EN */
setbits_le32(&regs->sdcc_hc_dll_config, SDCC_DLL_CONFIG_DLL_EN);
clrbits_le32(&regs->sdcc_hc_dll_config, SDCC_DLL_MCLK_GATING_EN);
clrbits_le32(&regs->sdcc_hc_dll_config, SDCC_DLL_CDR_FINE_PHASE);
/* Wait for CK_OUT_EN clear */
do {
val = readl(&regs->sdcc_hc_dll_config);
val &= SDCC_DLL_CONFIG_CK_OUT_EN;
if (!val)
break;
mdelay(1);
retry--;
} while (retry > 0);
if (!retry)
dev_err(dev, "Clear CK_OUT_EN timedout\n");
/* Set CK_OUT_EN */
setbits_le32(&regs->sdcc_hc_dll_config, SDCC_DLL_CONFIG_CK_OUT_EN);
/* Wait for CK_OUT_EN set */
retry = 1000;
do {
val = readl(&regs->sdcc_hc_dll_config);
val &= SDCC_DLL_CONFIG_CK_OUT_EN;
if (val)
break;
mdelay(1);
retry--;
} while (retry > 0);
if (!retry)
dev_err(dev, "Set CK_OUT_EN timedout\n");
/* Set DDR_CAL_EN */
setbits_le32(&regs->sdcc_hc_dll_config2, SDCC_DLL_CONFIG2_DDR_CAL_EN);
clrbits_le32(&regs->sdcc_hc_dll_config2,
SDCC_DLL_CONFIG2_DLL_CLOCK_DIS);
clrsetbits_le32(&regs->sdcc_hc_dll_config2,
SDCC_DLL_CONFIG2_MCLK_FREQ_CALC, 0x1A << 10);
clrsetbits_le32(&regs->sdcc_hc_dll_config2,
SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL, BIT(2));
setbits_le32(&regs->sdcc_hc_dll_config2,
SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW);
return 0;
}
static int ethqos_rgmii_macro_init(struct udevice *dev,
struct dwmac_rgmii_regs *regs,
unsigned long speed)
{
/* Disable loopback mode */
clrbits_le32(&regs->io_macro_config2,
RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN);
/* Select RGMII, write 0 to interface select */
clrbits_le32(&regs->io_macro_config, RGMII_CONFIG_INTF_SEL);
switch (speed) {
case SPEED_1000:
setbits_le32(&regs->io_macro_config, RGMII_CONFIG_DDR_MODE);
clrbits_le32(&regs->io_macro_config,
RGMII_CONFIG_BYPASS_TX_ID_EN);
setbits_le32(&regs->io_macro_config,
RGMII_CONFIG_POS_NEG_DATA_SEL);
setbits_le32(&regs->io_macro_config, RGMII_CONFIG_PROG_SWAP);
clrbits_le32(&regs->io_macro_config2,
RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL);
setbits_le32(&regs->io_macro_config2,
RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN);
clrbits_le32(&regs->io_macro_config2,
RGMII_CONFIG2_RSVD_CONFIG15);
setbits_le32(&regs->io_macro_config2,
RGMII_CONFIG2_RX_PROG_SWAP);
/* Set PRG_RCLK_DLY to 57 for 1.8 ns delay */
clrsetbits_le32(&regs->sdcc_hc_ddr_config,
SDCC_DDR_CONFIG_PRG_RCLK_DLY, 57);
setbits_le32(&regs->sdcc_hc_ddr_config, SDCC_DDR_CONFIG_PRG_DLY_EN);
setbits_le32(&regs->io_macro_config, RGMII_CONFIG_LOOPBACK_EN);
break;
case SPEED_100:
setbits_le32(&regs->io_macro_config, RGMII_CONFIG_DDR_MODE);
setbits_le32(&regs->io_macro_config,
RGMII_CONFIG_BYPASS_TX_ID_EN);
clrbits_le32(&regs->io_macro_config,
RGMII_CONFIG_POS_NEG_DATA_SEL);
clrbits_le32(&regs->io_macro_config, RGMII_CONFIG_PROG_SWAP);
clrsetbits_le32(&regs->io_macro_config,
RGMII_CONFIG_MAX_SPD_PRG_2, BIT(6));
clrbits_le32(&regs->io_macro_config2,
RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL);
setbits_le32(&regs->io_macro_config2,
RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN);
clrbits_le32(&regs->io_macro_config2,
RGMII_CONFIG2_RSVD_CONFIG15);
clrbits_le32(&regs->io_macro_config2,
RGMII_CONFIG2_RX_PROG_SWAP);
/* Write 0x5 to PRG_RCLK_DLY_CODE */
clrsetbits_le32(&regs->sdcc_hc_ddr_config,
SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
(BIT(29) | BIT(27)));
setbits_le32(&regs->sdcc_hc_ddr_config,
SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY);
setbits_le32(&regs->sdcc_hc_ddr_config,
SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN);
setbits_le32(&regs->io_macro_config, RGMII_CONFIG_LOOPBACK_EN);
break;
case SPEED_10:
setbits_le32(&regs->io_macro_config, RGMII_CONFIG_DDR_MODE);
setbits_le32(&regs->io_macro_config,
RGMII_CONFIG_BYPASS_TX_ID_EN);
clrbits_le32(&regs->io_macro_config,
RGMII_CONFIG_POS_NEG_DATA_SEL);
clrbits_le32(&regs->io_macro_config, RGMII_CONFIG_PROG_SWAP);
clrsetbits_le32(&regs->io_macro_config,
RGMII_CONFIG_MAX_SPD_PRG_9,
BIT(12) | GENMASK(9, 8));
clrbits_le32(&regs->io_macro_config2,
RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL);
clrbits_le32(&regs->io_macro_config2,
RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN);
clrbits_le32(&regs->io_macro_config2,
RGMII_CONFIG2_RSVD_CONFIG15);
clrbits_le32(&regs->io_macro_config2,
RGMII_CONFIG2_RX_PROG_SWAP);
/* Write 0x5 to PRG_RCLK_DLY_CODE */
clrsetbits_le32(&regs->sdcc_hc_ddr_config,
SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
(BIT(29) | BIT(27)));
setbits_le32(&regs->sdcc_hc_ddr_config,
SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY);
setbits_le32(&regs->sdcc_hc_ddr_config,
SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN);
setbits_le32(&regs->io_macro_config, RGMII_CONFIG_LOOPBACK_EN);
break;
default:
dev_err(dev, "Invalid speed %ld\n", speed);
return -EINVAL;
}
return 0;
}
static int ethqos_configure(struct udevice *dev,
struct dwmac_rgmii_regs *regs,
unsigned long speed)
{
unsigned int retry = 1000;
/* Reset to POR values and enable clk */
writel(emac_v2_3_0_por.io_macro_config, &regs->io_macro_config);
writel(emac_v2_3_0_por.sdcc_hc_dll_config, &regs->sdcc_hc_dll_config);
writel(emac_v2_3_0_por.sdcc_hc_ddr_config, &regs->sdcc_hc_ddr_config);
writel(emac_v2_3_0_por.sdcc_hc_dll_config2, &regs->sdcc_hc_dll_config2);
writel(emac_v2_3_0_por.sdcc_usr_ctl, &regs->sdcc_usr_ctl);
writel(emac_v2_3_0_por.io_macro_config2, &regs->io_macro_config2);
ethqos_set_func_clk_en(regs);
/* Initialize the DLL first */
/* Set DLL_RST */
setbits_le32(&regs->sdcc_hc_dll_config, SDCC_DLL_CONFIG_DLL_RST);
/* Set PDN */
setbits_le32(&regs->sdcc_hc_dll_config, SDCC_DLL_CONFIG_PDN);
/* Clear DLL_RST */
clrbits_le32(&regs->sdcc_hc_dll_config, SDCC_DLL_CONFIG_DLL_RST);
/* Clear PDN */
clrbits_le32(&regs->sdcc_hc_dll_config, SDCC_DLL_CONFIG_PDN);
if (speed == SPEED_1000) {
/* Set DLL_EN */
setbits_le32(&regs->sdcc_hc_dll_config, SDCC_DLL_CONFIG_DLL_EN);
/* Set CK_OUT_EN */
setbits_le32(&regs->sdcc_hc_dll_config,
SDCC_DLL_CONFIG_CK_OUT_EN);
/* Set USR_CTL bit 26 with mask of 3 bits */
clrsetbits_le32(&regs->sdcc_usr_ctl, GENMASK(26, 24), BIT(26));
/* wait for DLL LOCK */
do {
mdelay(1);
if (readl(&regs->sdc4_status) & SDC4_STATUS_DLL_LOCK)
break;
retry--;
} while (retry > 0);
if (!retry)
dev_err(dev, "Timeout while waiting for DLL lock\n");
ethqos_dll_configure(dev, regs);
}
ethqos_rgmii_macro_init(dev, regs, speed);
return 0;
}
static void ethqos_rgmii_dump(struct udevice *dev,
struct dwmac_rgmii_regs *regs)
{
dev_dbg(dev, "Rgmii register dump\n");
dev_dbg(dev, "RGMII_IO_MACRO_CONFIG: %08x\n",
readl(&regs->io_macro_config));
dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG: %08x\n",
readl(&regs->sdcc_hc_dll_config));
dev_dbg(dev, "SDCC_HC_REG_DDR_CONFIG: %08x\n",
readl(&regs->sdcc_hc_ddr_config));
dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG2: %08x\n",
readl(&regs->sdcc_hc_dll_config2));
dev_dbg(dev, "SDC4_STATUS: %08x\n",
readl(&regs->sdc4_status));
dev_dbg(dev, "SDCC_USR_CTL: %08x\n",
readl(&regs->sdcc_usr_ctl));
dev_dbg(dev, "RGMII_IO_MACRO_CONFIG2: %08x\n",
readl(&regs->io_macro_config2));
dev_dbg(dev, "RGMII_IO_MACRO_DEBUG1: %08x\n",
readl(&regs->io_macro_debug1));
dev_dbg(dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %08x\n",
readl(&regs->emac_sys_low_power_dbg));
}
static int qcom_eqos_rgmii_set_speed(struct udevice *dev,
void *rgmii_regs,
unsigned long speed)
{
int ret;
ethqos_rgmii_dump(dev, rgmii_regs);
ret = ethqos_configure(dev, rgmii_regs, speed);
if (ret)
return ret;
ethqos_rgmii_dump(dev, rgmii_regs);
return 0;
}
static int qcom_eqos_rgmii_reset(struct udevice *dev, void *rgmii_regs)
{
ethqos_set_func_clk_en(rgmii_regs);
return 0;
}
static int eqos_start_clks_qcom(struct udevice *dev)
{
if (IS_ENABLED(CONFIG_CLK)) {
struct clk_bulk clocks;
int ret;
ret = clk_get_bulk(dev, &clocks);
if (ret)
return ret;
ret = clk_enable_bulk(&clocks);
if (ret)
return ret;
}
debug("%s: OK\n", __func__);
return 0;
}
static int eqos_stop_clks_qcom(struct udevice *dev)
{
if (IS_ENABLED(CONFIG_CLK)) {
struct clk_bulk clocks;
int ret;
ret = clk_get_bulk(dev, &clocks);
if (ret)
return ret;
ret = clk_disable_bulk(&clocks);
if (ret)
return ret;
}
debug("%s: OK\n", __func__);
return 0;
}
static int eqos_start_resets_qcom(struct udevice *dev)
{
struct eqos_priv *eqos = dev_get_priv(dev);
int ret;
debug("%s(dev=%p):\n", __func__, dev);
if (!eqos->phy) {
ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0);
if (ret < 0) {
pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d", ret);
return ret;
}
udelay(eqos->reset_delays[0]);
ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1);
if (ret < 0) {
pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", ret);
return ret;
}
udelay(eqos->reset_delays[1]);
ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0);
if (ret < 0) {
pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", ret);
return ret;
}
udelay(eqos->reset_delays[2]);
}
ret = reset_deassert(&eqos->reset_ctl);
if (ret < 0) {
pr_err("reset_deassert() failed: %d", ret);
return ret;
}
ret = qcom_eqos_rgmii_reset(dev, eqos->eqos_qcom_rgmii_regs);
if (ret < 0) {
pr_err("qcom rgmii_reset failed: %d", ret);
return ret;
}
debug("%s: OK\n", __func__);
return 0;
}
/* Clock rates */
#define RGMII_1000_NOM_CLK_FREQ (250 * 1000 * 1000UL)
#define RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ (50 * 1000 * 1000UL)
#define RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ (5 * 1000 * 1000UL)
static int eqos_set_tx_clk_speed_qcom(struct udevice *dev)
{
struct eqos_priv *eqos = dev_get_priv(dev);
ulong rate;
int ret;
debug("%s(dev=%p):\n", __func__, dev);
switch (eqos->phy->speed) {
case SPEED_1000:
rate = RGMII_1000_NOM_CLK_FREQ;
break;
case SPEED_100:
rate = RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ;
break;
case SPEED_10:
rate = RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ;
break;
default:
pr_err("invalid speed %d", eqos->phy->speed);
return -EINVAL;
}
ret = clk_set_rate(&eqos->clk_tx, rate);
if (ret < 0) {
pr_err("clk_set_rate(tx_clk, %lu) failed: %d", rate, ret);
return ret;
}
ret = qcom_eqos_rgmii_set_speed(dev, eqos->eqos_qcom_rgmii_regs,
eqos->phy->speed);
if (ret < 0) {
pr_err("qcom set_speed: %d, failed: %d", eqos->phy->speed, ret);
return ret;
}
return 0;
}
static int eqos_probe_resources_qcom(struct udevice *dev)
{
struct eqos_priv *eqos = dev_get_priv(dev);
phy_interface_t interface;
int reset_flags = GPIOD_IS_OUT;
int ret;
debug("%s(dev=%p):\n", __func__, dev);
interface = eqos->config->interface(dev);
if (interface == PHY_INTERFACE_MODE_NA) {
pr_err("Invalid PHY interface\n");
return -EINVAL;
}
eqos->max_speed = dev_read_u32_default(dev, "max-speed", 0);
eqos->tx_fifo_sz = dev_read_u32_default(dev, "tx-fifo-depth", 0);
eqos->rx_fifo_sz = dev_read_u32_default(dev, "rx-fifo-depth", 0);
ret = reset_get_by_name(dev, "emac", &eqos->reset_ctl);
if (ret) {
pr_err("reset_get_by_name(rst) failed: %d", ret);
return ret;
}
if (dev_read_bool(dev, "snps,reset-active-low"))
reset_flags |= GPIOD_ACTIVE_LOW;
ret = gpio_request_by_name(dev, "snps,reset-gpio", 0,
&eqos->phy_reset_gpio, reset_flags);
if (ret == 0) {
ret = dev_read_u32_array(dev, "snps,reset-delays-us",
eqos->reset_delays, 3);
} else if (ret == -ENOENT) {
ret = 0;
}
eqos->eqos_qcom_rgmii_regs = (void *)dev_read_addr_name(dev, "rgmii");
if ((fdt_addr_t)eqos->eqos_qcom_rgmii_regs == FDT_ADDR_T_NONE) {
pr_err("Invalid RGMII address\n");
return -EINVAL;
}
ret = clk_get_by_name(dev, "rgmii", &eqos->clk_tx);
if (ret) {
pr_err("clk_get_by_name(tx) failed: %d", ret);
return -EINVAL;
}
debug("%s: OK\n", __func__);
return 0;
}
static int eqos_remove_resources_qcom(struct udevice *dev)
{
struct eqos_priv *eqos = dev_get_priv(dev);
debug("%s(dev=%p):\n", __func__, dev);
clk_free(&eqos->clk_tx);
dm_gpio_free(dev, &eqos->phy_reset_gpio);
reset_free(&eqos->reset_ctl);
debug("%s: OK\n", __func__);
return 0;
}
static struct eqos_ops eqos_qcom_ops = {
.eqos_inval_desc = eqos_inval_desc_generic,
.eqos_flush_desc = eqos_flush_desc_generic,
.eqos_inval_buffer = eqos_inval_buffer_generic,
.eqos_flush_buffer = eqos_flush_buffer_generic,
.eqos_probe_resources = eqos_probe_resources_qcom,
.eqos_remove_resources = eqos_remove_resources_qcom,
.eqos_stop_resets = eqos_null_ops,
.eqos_start_resets = eqos_start_resets_qcom,
.eqos_stop_clks = eqos_stop_clks_qcom,
.eqos_start_clks = eqos_start_clks_qcom,
.eqos_calibrate_pads = eqos_null_ops,
.eqos_disable_calibration = eqos_null_ops,
.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_qcom,
.eqos_get_enetaddr = eqos_null_ops,
};
struct eqos_config __maybe_unused eqos_qcom_config = {
.reg_access_always_ok = false,
.mdio_wait = 10,
.swr_wait = 50,
.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300,
.axi_bus_width = EQOS_AXI_WIDTH_64,
.interface = dev_read_phy_mode,
.ops = &eqos_qcom_ops
};

View file

@ -12,9 +12,13 @@
#include <env.h> #include <env.h>
#include <malloc.h> #include <malloc.h>
#include <net.h> #include <net.h>
#include <phy.h>
#include <miiphy.h>
#include <dm/device_compat.h>
#include <asm/global_data.h> #include <asm/global_data.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/iopoll.h>
#include "ftmac100.h" #include "ftmac100.h"
#include <dm.h> #include <dm.h>
@ -23,12 +27,16 @@ DECLARE_GLOBAL_DATA_PTR;
#define ETH_ZLEN 60 #define ETH_ZLEN 60
/* Timeout for a mdio read/write operation */
#define FTMAC100_MDIO_TIMEOUT_USEC 10000
struct ftmac100_data { struct ftmac100_data {
struct ftmac100_txdes txdes[1]; struct ftmac100_txdes txdes[1];
struct ftmac100_rxdes rxdes[PKTBUFSRX]; struct ftmac100_rxdes rxdes[PKTBUFSRX];
int rx_index; int rx_index;
const char *name; const char *name;
phys_addr_t iobase; struct ftmac100 *ftmac100;
struct mii_dev *bus;
}; };
/* /*
@ -36,7 +44,7 @@ struct ftmac100_data {
*/ */
static void ftmac100_reset(struct ftmac100_data *priv) static void ftmac100_reset(struct ftmac100_data *priv)
{ {
struct ftmac100 *ftmac100 = (struct ftmac100 *)(uintptr_t)priv->iobase; struct ftmac100 *ftmac100 = priv->ftmac100;
debug ("%s()\n", __func__); debug ("%s()\n", __func__);
@ -57,7 +65,7 @@ static void ftmac100_reset(struct ftmac100_data *priv)
static void ftmac100_set_mac(struct ftmac100_data *priv , static void ftmac100_set_mac(struct ftmac100_data *priv ,
const unsigned char *mac) const unsigned char *mac)
{ {
struct ftmac100 *ftmac100 = (struct ftmac100 *)(uintptr_t)priv->iobase; struct ftmac100 *ftmac100 = priv->ftmac100;
unsigned int maddr = mac[0] << 8 | mac[1]; unsigned int maddr = mac[0] << 8 | mac[1];
unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5]; unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
@ -72,7 +80,7 @@ static void ftmac100_set_mac(struct ftmac100_data *priv ,
*/ */
static void _ftmac100_halt(struct ftmac100_data *priv) static void _ftmac100_halt(struct ftmac100_data *priv)
{ {
struct ftmac100 *ftmac100 = (struct ftmac100 *)(uintptr_t)priv->iobase; struct ftmac100 *ftmac100 = priv->ftmac100;
debug ("%s()\n", __func__); debug ("%s()\n", __func__);
writel (0, &ftmac100->maccr); writel (0, &ftmac100->maccr);
} }
@ -82,7 +90,7 @@ static void _ftmac100_halt(struct ftmac100_data *priv)
*/ */
static int _ftmac100_init(struct ftmac100_data *priv, unsigned char enetaddr[6]) static int _ftmac100_init(struct ftmac100_data *priv, unsigned char enetaddr[6])
{ {
struct ftmac100 *ftmac100 = (struct ftmac100 *)(uintptr_t)priv->iobase; struct ftmac100 *ftmac100 = priv->ftmac100;
struct ftmac100_txdes *txdes = priv->txdes; struct ftmac100_txdes *txdes = priv->txdes;
struct ftmac100_rxdes *rxdes = priv->rxdes; struct ftmac100_rxdes *rxdes = priv->rxdes;
unsigned int maccr; unsigned int maccr;
@ -187,7 +195,7 @@ static int __ftmac100_recv(struct ftmac100_data *priv)
*/ */
static int _ftmac100_send(struct ftmac100_data *priv, void *packet, int length) static int _ftmac100_send(struct ftmac100_data *priv, void *packet, int length)
{ {
struct ftmac100 *ftmac100 = (struct ftmac100 *)(uintptr_t)priv->iobase; struct ftmac100 *ftmac100 = priv->ftmac100;
struct ftmac100_txdes *curr_des = priv->txdes; struct ftmac100_txdes *curr_des = priv->txdes;
ulong start; ulong start;
@ -314,7 +322,7 @@ static int ftmac100_of_to_plat(struct udevice *dev)
struct eth_pdata *pdata = dev_get_plat(dev); struct eth_pdata *pdata = dev_get_plat(dev);
const char *mac; const char *mac;
pdata->iobase = dev_read_addr(dev); pdata->iobase = dev_read_addr(dev);
priv->iobase = pdata->iobase; priv->ftmac100 = phys_to_virt(pdata->iobase);
mac = dtbmacaddr(0); mac = dtbmacaddr(0);
if (mac) if (mac)
memcpy(pdata->enetaddr , mac , 6); memcpy(pdata->enetaddr , mac , 6);
@ -322,10 +330,104 @@ static int ftmac100_of_to_plat(struct udevice *dev)
return 0; return 0;
} }
/*
* struct mii_bus functions
*/
static int ftmac100_mdio_read(struct mii_dev *bus, int addr, int devad,
int reg)
{
struct ftmac100_data *priv = bus->priv;
struct ftmac100 *ftmac100 = priv->ftmac100;
int phycr = FTMAC100_PHYCR_PHYAD(addr) |
FTMAC100_PHYCR_REGAD(reg) |
FTMAC100_PHYCR_MIIRD;
int ret;
writel(phycr, &ftmac100->phycr);
ret = readl_poll_timeout(&ftmac100->phycr, phycr,
!(phycr & FTMAC100_PHYCR_MIIRD),
FTMAC100_MDIO_TIMEOUT_USEC);
if (ret)
pr_err("%s: mdio read failed (addr=0x%x reg=0x%x)\n",
bus->name, addr, reg);
else
ret = phycr & FTMAC100_PHYCR_MIIRDATA;
return ret;
}
static int ftmac100_mdio_write(struct mii_dev *bus, int addr, int devad,
int reg, u16 value)
{
struct ftmac100_data *priv = bus->priv;
struct ftmac100 *ftmac100 = priv->ftmac100;
int phycr = FTMAC100_PHYCR_PHYAD(addr) |
FTMAC100_PHYCR_REGAD(reg) |
FTMAC100_PHYCR_MIIWR;
int ret;
writel(value, &ftmac100->phywdata);
writel(phycr, &ftmac100->phycr);
ret = readl_poll_timeout(&ftmac100->phycr, phycr,
!(phycr & FTMAC100_PHYCR_MIIWR),
FTMAC100_MDIO_TIMEOUT_USEC);
if (ret)
pr_err("%s: mdio write failed (addr=0x%x reg=0x%x)\n",
bus->name, addr, reg);
return ret;
}
static int ftmac100_mdio_init(struct udevice *dev)
{
struct ftmac100_data *priv = dev_get_priv(dev);
struct mii_dev *bus;
int ret;
bus = mdio_alloc();
if (!bus)
return -ENOMEM;
bus->read = ftmac100_mdio_read;
bus->write = ftmac100_mdio_write;
bus->priv = priv;
ret = mdio_register_seq(bus, dev_seq(dev));
if (ret) {
mdio_free(bus);
return ret;
}
priv->bus = bus;
return 0;
}
static int ftmac100_probe(struct udevice *dev) static int ftmac100_probe(struct udevice *dev)
{ {
struct ftmac100_data *priv = dev_get_priv(dev); struct ftmac100_data *priv = dev_get_priv(dev);
priv->name = dev->name; priv->name = dev->name;
int ret = 0;
ret = ftmac100_mdio_init(dev);
if (ret) {
dev_err(dev, "Failed to initialize mdiobus: %d\n", ret);
goto out;
}
out:
return ret;
}
static int ftmac100_remove(struct udevice *dev)
{
struct ftmac100_data *priv = dev_get_priv(dev);
mdio_unregister(priv->bus);
mdio_free(priv->bus);
return 0; return 0;
} }
@ -348,12 +450,13 @@ static const struct udevice_id ftmac100_ids[] = {
}; };
U_BOOT_DRIVER(ftmac100) = { U_BOOT_DRIVER(ftmac100) = {
.name = "nds32_mac", .name = "ftmac100",
.id = UCLASS_ETH, .id = UCLASS_ETH,
.of_match = ftmac100_ids, .of_match = ftmac100_ids,
.bind = ftmac100_bind, .bind = ftmac100_bind,
.of_to_plat = ftmac100_of_to_plat, .of_to_plat = ftmac100_of_to_plat,
.probe = ftmac100_probe, .probe = ftmac100_probe,
.remove = ftmac100_remove,
.ops = &ftmac100_ops, .ops = &ftmac100_ops,
.priv_auto = sizeof(struct ftmac100_data), .priv_auto = sizeof(struct ftmac100_data),
.plat_auto = sizeof(struct eth_pdata), .plat_auto = sizeof(struct eth_pdata),

View file

@ -92,6 +92,15 @@ struct ftmac100 {
#define FTMAC100_MACCR_RX_MULTIPKT (1 << 16) #define FTMAC100_MACCR_RX_MULTIPKT (1 << 16)
#define FTMAC100_MACCR_RX_BROADPKT (1 << 17) #define FTMAC100_MACCR_RX_BROADPKT (1 << 17)
/*
* PHY control register
*/
#define FTMAC100_PHYCR_MIIRDATA 0xffff
#define FTMAC100_PHYCR_PHYAD(x) (((x) & 0x1f) << 16)
#define FTMAC100_PHYCR_REGAD(x) (((x) & 0x1f) << 21)
#define FTMAC100_PHYCR_MIIWR BIT(27)
#define FTMAC100_PHYCR_MIIRD BIT(26)
/* /*
* Transmit descriptor, aligned to 16 bytes * Transmit descriptor, aligned to 16 bytes
*/ */

1
env/Kconfig vendored
View file

@ -733,6 +733,7 @@ config ENV_APPEND
config ENV_WRITEABLE_LIST config ENV_WRITEABLE_LIST
bool "Permit write access only to listed variables" bool "Permit write access only to listed variables"
select ENV_APPEND
help help
If defined, only environment variables which explicitly set the 'w' If defined, only environment variables which explicitly set the 'w'
writeable flag can be written and modified at runtime. No variables writeable flag can be written and modified at runtime. No variables

8
env/env.c vendored
View file

@ -192,6 +192,14 @@ int env_load(void)
int best_prio = -1; int best_prio = -1;
int prio; int prio;
if (CONFIG_IS_ENABLED(ENV_WRITEABLE_LIST)) {
/*
* When using a list of writeable variables, the baseline comes
* from the built-in default env. So load this first.
*/
env_set_default(NULL, 0);
}
for (prio = 0; (drv = env_driver_lookup(ENVOP_LOAD, prio)); prio++) { for (prio = 0; (drv = env_driver_lookup(ENVOP_LOAD, prio)); prio++) {
int ret; int ret;

10
env/flags.c vendored
View file

@ -22,7 +22,7 @@
#include <env_internal.h> #include <env_internal.h>
#endif #endif
#ifdef CONFIG_CMD_NET #ifdef CONFIG_NET
#define ENV_FLAGS_NET_VARTYPE_REPS "im" #define ENV_FLAGS_NET_VARTYPE_REPS "im"
#else #else
#define ENV_FLAGS_NET_VARTYPE_REPS "" #define ENV_FLAGS_NET_VARTYPE_REPS ""
@ -57,7 +57,7 @@ static const char * const env_flags_vartype_names[] = {
"decimal", "decimal",
"hexadecimal", "hexadecimal",
"boolean", "boolean",
#ifdef CONFIG_CMD_NET #ifdef CONFIG_NET
"IP address", "IP address",
"MAC address", "MAC address",
#endif #endif
@ -211,7 +211,7 @@ static void skip_num(int hex, const char *value, const char **end,
*end = value; *end = value;
} }
#ifdef CONFIG_CMD_NET #ifdef CONFIG_NET
int eth_validate_ethaddr_str(const char *addr) int eth_validate_ethaddr_str(const char *addr)
{ {
const char *end; const char *end;
@ -244,7 +244,7 @@ static int _env_flags_validate_type(const char *value,
enum env_flags_vartype type) enum env_flags_vartype type)
{ {
const char *end; const char *end;
#ifdef CONFIG_CMD_NET #ifdef CONFIG_NET
const char *cur; const char *cur;
int i; int i;
#endif #endif
@ -273,7 +273,7 @@ static int _env_flags_validate_type(const char *value,
if (value[1] != '\0') if (value[1] != '\0')
return -1; return -1;
break; break;
#ifdef CONFIG_CMD_NET #ifdef CONFIG_NET
case env_flags_vartype_ipaddr: case env_flags_vartype_ipaddr:
cur = value; cur = value;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {

View file

@ -37,6 +37,14 @@ struct button_ops {
* @return button state button_state_t, or -ve on error * @return button state button_state_t, or -ve on error
*/ */
enum button_state_t (*get_state)(struct udevice *dev); enum button_state_t (*get_state)(struct udevice *dev);
/**
* get_code() - get linux event code of a button
*
* @dev: button device to change
* @return button code, or -ENODATA on error
*/
int (*get_code)(struct udevice *dev);
}; };
#define button_get_ops(dev) ((struct button_ops *)(dev)->driver->ops) #define button_get_ops(dev) ((struct button_ops *)(dev)->driver->ops)
@ -58,4 +66,12 @@ int button_get_by_label(const char *label, struct udevice **devp);
*/ */
enum button_state_t button_get_state(struct udevice *dev); enum button_state_t button_get_state(struct udevice *dev);
/**
* button_get_code() - get linux event code of a button
*
* @dev: button device to change
* @return button code, or -ve on error
*/
int button_get_code(struct udevice *dev);
#endif #endif

View file

@ -10,8 +10,6 @@
#ifndef __CONFIG_H #ifndef __CONFIG_H
#define __CONFIG_H #define __CONFIG_H
#define CFG_SYS_NS16550_COM1 0xf040c000
#define CFG_SYS_INIT_RAM_ADDR 0x10200000 #define CFG_SYS_INIT_RAM_ADDR 0x10200000
#include "bcmstb.h" #include "bcmstb.h"

View file

@ -10,8 +10,6 @@
#ifndef __CONFIG_H #ifndef __CONFIG_H
#define __CONFIG_H #define __CONFIG_H
#define CFG_SYS_NS16550_COM1 0xf040ab00
#define CFG_SYS_INIT_RAM_ADDR 0x80200000 #define CFG_SYS_INIT_RAM_ADDR 0x80200000
#include "bcmstb.h" #include "bcmstb.h"

View file

@ -92,19 +92,6 @@ extern phys_addr_t prior_stage_fdt_address;
* Large kernel image bootm configuration. * Large kernel image bootm configuration.
*/ */
/*
* NS16550 configuration.
*/
#define V_NS16550_CLK 81000000
#define CFG_SYS_NS16550_CLK V_NS16550_CLK
/*
* Serial console configuration.
*/
#define CFG_SYS_BAUDRATE_TABLE {4800, 9600, 19200, 38400, 57600, \
115200}
/* /*
* Informational display configuration. * Informational display configuration.
*/ */

View file

@ -1,22 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* This header provides constants for Qualcomm Snapdragon pinctrl bindings.
*
* (C) Copyright 2018 Ramon Fried <ramon.fried@gmail.com>
*
*/
#ifndef _DT_BINDINGS_PINCTRL_SNAPDRAGON_H
#define _DT_BINDINGS_PINCTRL_SNAPDRAGON_H
/* GPIO Drive Strength */
#define DRIVE_STRENGTH_2MA 0
#define DRIVE_STRENGTH_4MA 1
#define DRIVE_STRENGTH_6MA 2
#define DRIVE_STRENGTH_8MA 3
#define DRIVE_STRENGTH_10MA 4
#define DRIVE_STRENGTH_12MA 5
#define DRIVE_STRENGTH_14MA 6
#define DRIVE_STRENGTH_16MA 7
#endif

View file

@ -12,7 +12,7 @@ enum env_flags_vartype {
env_flags_vartype_decimal, env_flags_vartype_decimal,
env_flags_vartype_hex, env_flags_vartype_hex,
env_flags_vartype_bool, env_flags_vartype_bool,
#ifdef CONFIG_CMD_NET #ifdef CONFIG_NET
env_flags_vartype_ipaddr, env_flags_vartype_ipaddr,
env_flags_vartype_macaddr, env_flags_vartype_macaddr,
#endif #endif
@ -121,7 +121,7 @@ enum env_flags_varaccess env_flags_parse_varaccess(const char *flags);
*/ */
enum env_flags_varaccess env_flags_parse_varaccess_from_binflags(int binflags); enum env_flags_varaccess env_flags_parse_varaccess_from_binflags(int binflags);
#ifdef CONFIG_CMD_NET #ifdef CONFIG_NET
/* /*
* Check if a string has the format of an Ethernet MAC address * Check if a string has the format of an Ethernet MAC address
*/ */

View file

@ -13,6 +13,7 @@
#include <power/sandbox_pmic.h> #include <power/sandbox_pmic.h>
#include <asm/gpio.h> #include <asm/gpio.h>
#include <dm/test.h> #include <dm/test.h>
#include <dt-bindings/input/input.h>
#include <test/ut.h> #include <test/ut.h>
/* Base test of the button uclass */ /* Base test of the button uclass */
@ -85,6 +86,18 @@ static int dm_test_button_label(struct unit_test_state *uts)
} }
DM_TEST(dm_test_button_label, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); DM_TEST(dm_test_button_label, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
/* Test button has linux,code */
static int dm_test_button_linux_code(struct unit_test_state *uts)
{
struct udevice *dev;
ut_assertok(uclass_get_device(UCLASS_BUTTON, 1, &dev));
ut_asserteq(BTN_1, button_get_code(dev));
return 0;
}
DM_TEST(dm_test_button_linux_code, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
/* Test adc-keys driver */ /* Test adc-keys driver */
static int dm_test_button_keys_adc(struct unit_test_state *uts) static int dm_test_button_keys_adc(struct unit_test_state *uts)
{ {

View file

@ -1046,7 +1046,7 @@ static int dm_test_ofnode_for_each_prop(struct unit_test_state *uts)
struct ofprop prop; struct ofprop prop;
int count; int count;
node = ofnode_path("/buttons"); node = ofnode_path("/ofnode-foreach");
count = 0; count = 0;
/* we expect "compatible" for each node */ /* we expect "compatible" for each node */