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:
commit
a1e6b529e5
49 changed files with 1958 additions and 81 deletions
|
@ -72,7 +72,7 @@
|
|||
|
||||
record {
|
||||
label = "Record";
|
||||
/* linux,code = <BTN_0>; */
|
||||
linux,code = <KEY_RECORD>;
|
||||
gpios = <&tca6416_2 15 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include "skeleton64.dtsi"
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/pinctrl/pinctrl-snapdragon.h>
|
||||
|
||||
/ {
|
||||
model = "Qualcomm Technologies, Inc. Dragonboard 410c";
|
||||
|
@ -71,7 +70,7 @@
|
|||
blsp1_uart: uart {
|
||||
function = "blsp1_uart";
|
||||
pins = "GPIO_4", "GPIO_5";
|
||||
drive-strength = <DRIVE_STRENGTH_8MA>;
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
/dts-v1/;
|
||||
|
||||
#include "skeleton64.dtsi"
|
||||
#include <dt-bindings/pinctrl/pinctrl-snapdragon.h>
|
||||
|
||||
/ {
|
||||
model = "Qualcomm Technologies, Inc. DB820c";
|
||||
|
@ -71,7 +70,7 @@
|
|||
blsp8_uart: uart {
|
||||
function = "blsp_uart8";
|
||||
pins = "GPIO_4", "GPIO_5";
|
||||
drive-strength = <DRIVE_STRENGTH_8MA>;
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
/ {
|
||||
gpio_keys: gpio-keys {
|
||||
compatible = "gpio-key";
|
||||
compatible = "gpio-keys";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_gpio_keys>;
|
||||
status = "disabled";
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include "skeleton.dtsi"
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/pinctrl/pinctrl-snapdragon.h>
|
||||
#include <dt-bindings/clock/qcom,ipq4019-gcc.h>
|
||||
#include <dt-bindings/reset/qcom,ipq4019-reset.h>
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include "skeleton64.dtsi"
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/pinctrl/pinctrl-snapdragon.h>
|
||||
#include <dt-bindings/clock/qcom,gcc-qcs404.h>
|
||||
|
||||
/ {
|
||||
|
@ -24,6 +23,11 @@
|
|||
|
||||
aliases {
|
||||
serial0 = &debug_uart;
|
||||
i2c0 = &blsp1_i2c0;
|
||||
i2c1 = &blsp1_i2c1;
|
||||
i2c2 = &blsp1_i2c2;
|
||||
i2c3 = &blsp1_i2c3;
|
||||
i2c4 = &blsp1_i2c4;
|
||||
};
|
||||
|
||||
memory {
|
||||
|
@ -37,14 +41,165 @@
|
|||
ranges = <0x0 0x0 0x0 0xffffffff>;
|
||||
compatible = "simple-bus";
|
||||
|
||||
pinctrl_north@1300000 {
|
||||
soc_gpios: pinctrl_north@1300000 {
|
||||
compatible = "qcom,qcs404-pinctrl";
|
||||
reg = <0x1300000 0x200000>;
|
||||
gpio-controller;
|
||||
gpio-count = <120>;
|
||||
gpio-bank-name="soc";
|
||||
#gpio-cells = <2>;
|
||||
|
||||
blsp1_uart2: uart {
|
||||
pins = "GPIO_17", "GPIO_18";
|
||||
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 {
|
||||
|
@ -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 = <ðernet_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 {
|
||||
compatible = "qcom,spmi-pmic-arb";
|
||||
reg = <0x200f000 0x1000
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include "rk3288.dtsi"
|
||||
|
||||
/ {
|
||||
|
@ -63,6 +64,7 @@
|
|||
power {
|
||||
gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
|
||||
label = "GPIO Key Power";
|
||||
linux,code = <KEY_POWER>;
|
||||
linux,input-type = <1>;
|
||||
wakeup-source;
|
||||
debounce-interval = <100>;
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include "rk3288.dtsi"
|
||||
|
||||
/ {
|
||||
|
@ -63,6 +64,7 @@
|
|||
button@0 {
|
||||
gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
|
||||
label = "GPIO Key Power";
|
||||
linux,code = <KEY_POWER>;
|
||||
linux,input-type = <1>;
|
||||
gpio-key,wakeup = <1>;
|
||||
debounce-interval = <100>;
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
/* GPLL0 clock control registers */
|
||||
#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 = {
|
||||
.cbcr_reg = BLSP1_AHB_CBCR,
|
||||
.ena_vote = APCS_CLOCK_BRANCH_ENA_VOTE,
|
||||
|
@ -47,6 +50,13 @@ static struct pll_vote_clk gpll0_vote_clk = {
|
|||
.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 = {
|
||||
.cfg_rcgr = USB30_MASTER_CFG_RCGR,
|
||||
.cmd_rcgr = USB30_MASTER_CMD_RCGR,
|
||||
|
@ -55,6 +65,22 @@ static const struct bcr_regs usb30_master_regs = {
|
|||
.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)
|
||||
{
|
||||
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:
|
||||
clk_enable_cbc(priv->base + SDCC_AHB_CBCR(1));
|
||||
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:
|
||||
return 0;
|
||||
}
|
||||
|
@ -111,6 +151,26 @@ int msm_enable(struct clk *clk)
|
|||
case GCC_USB2A_PHY_SLEEP_CLK:
|
||||
clk_enable_cbc(priv->base + USB_HS_PHY_CFG_AHB_CBCR);
|
||||
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:
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
struct msm_clk_priv *priv = dev_get_priv(dev);
|
||||
|
|
|
@ -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_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs,
|
||||
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
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
/* Clocks: (from CLK_CTL_BASE) */
|
||||
#define GPLL0_STATUS (0x21000)
|
||||
#define GPLL1_STATUS (0x20000)
|
||||
#define APCS_GPLL_ENA_VOTE (0x45000)
|
||||
#define APCS_CLOCK_BRANCH_ENA_VOTE (0x45004)
|
||||
|
||||
|
@ -54,4 +55,17 @@
|
|||
#define USB2A_PHY_SLEEP_CBCR (0x4102C)
|
||||
#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
|
||||
|
|
|
@ -22,6 +22,19 @@ static const char * const msm_pinctrl_pins[] = {
|
|||
|
||||
static const struct pinctrl_function msm_pinctrl_functions[] = {
|
||||
{"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,
|
||||
|
|
|
@ -28,8 +28,9 @@ struct msm_pinctrl_priv {
|
|||
#define TLMM_GPIO_DISABLE BIT(9)
|
||||
|
||||
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-pull-up", PIN_CONFIG_BIAS_PULL_UP, 3 },
|
||||
};
|
||||
|
||||
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) {
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
argument = (argument / 2) - 1;
|
||||
clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector),
|
||||
TLMM_DRV_STRENGTH_MASK, argument << 6);
|
||||
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),
|
||||
TLMM_GPIO_PULL_MASK);
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector),
|
||||
TLMM_GPIO_PULL_MASK, argument);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,19 @@ static struct mm_region qcs404_mem_map[] = {
|
|||
}, {
|
||||
.virt = 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) |
|
||||
PTE_BLOCK_INNER_SHARE
|
||||
}, {
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
* and sandbox64 builds.
|
||||
*/
|
||||
|
||||
#include <dt-bindings/input/input.h>
|
||||
|
||||
#define USB_CLASS_HUB 9
|
||||
|
||||
/ {
|
||||
|
@ -36,11 +38,13 @@
|
|||
btn1 {
|
||||
gpios = <&gpio_a 3 0>;
|
||||
label = "button1";
|
||||
linux,code = <BTN_1>;
|
||||
};
|
||||
|
||||
btn2 {
|
||||
gpios = <&gpio_a 4 0>;
|
||||
label = "button2";
|
||||
linux,code = <BTN_2>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -172,11 +172,13 @@
|
|||
btn1 {
|
||||
gpios = <&gpio_a 3 0>;
|
||||
label = "button1";
|
||||
linux,code = <BTN_1>;
|
||||
};
|
||||
|
||||
btn2 {
|
||||
gpios = <&gpio_a 4 0>;
|
||||
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 {
|
||||
compatible = "sandbox,sandbox_osd";
|
||||
};
|
||||
|
|
|
@ -2670,7 +2670,7 @@ static const struct eficonfig_item maintenance_menu_items[] = {
|
|||
{"Edit Boot Option", eficonfig_process_edit_boot_option},
|
||||
{"Change Boot Order", eficonfig_process_change_boot_order},
|
||||
{"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},
|
||||
#endif
|
||||
{"Quit", eficonfig_process_quit},
|
||||
|
|
|
@ -40,6 +40,6 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
|||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_BCMSTB=y
|
||||
CONFIG_MTD=y
|
||||
CONFIG_SYS_NS16550_SERIAL=y
|
||||
CONFIG_SYS_NS16550_REG_SIZE=-4
|
||||
CONFIG_DM_SERIAL=y
|
||||
CONFIG_SYS_NS16550=y
|
||||
# CONFIG_EFI_LOADER is not set
|
||||
|
|
|
@ -44,8 +44,8 @@ CONFIG_MTD=y
|
|||
CONFIG_DM_SPI_FLASH=y
|
||||
CONFIG_SPI_FLASH_MACRONIX=y
|
||||
CONFIG_SPI_FLASH_STMICRO=y
|
||||
CONFIG_SYS_NS16550_SERIAL=y
|
||||
CONFIG_SYS_NS16550_REG_SIZE=-4
|
||||
CONFIG_DM_SERIAL=y
|
||||
CONFIG_SYS_NS16550=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_DM_SPI=y
|
||||
CONFIG_BCMSTB_SPI=y
|
||||
|
|
|
@ -44,6 +44,7 @@ CONFIG_DM_PMIC=y
|
|||
CONFIG_PMIC_QCOM=y
|
||||
CONFIG_DM_RESET=y
|
||||
CONFIG_MSM_SERIAL=y
|
||||
CONFIG_MSM_GPIO=y
|
||||
CONFIG_SPMI_MSM=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_XHCI_HCD=y
|
||||
|
|
|
@ -31,6 +31,12 @@ ${CROSS_COMPILE}strip u-boot
|
|||
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.
|
||||
For example:
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
struct button_gpio_priv {
|
||||
struct gpio_desc gpio;
|
||||
int linux_code;
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
ret = dev_read_u32(dev, "linux,code", &priv->linux_code);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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 = {
|
||||
.get_state = button_gpio_get_state,
|
||||
.get_code = button_gpio_get_code,
|
||||
};
|
||||
|
||||
static const struct udevice_id button_gpio_ids[] = {
|
||||
|
|
|
@ -38,6 +38,16 @@ enum button_state_t button_get_state(struct udevice *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) = {
|
||||
.id = UCLASS_BUTTON,
|
||||
.name = "button",
|
||||
|
|
|
@ -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 = {
|
||||
.get_value = qcom_pwrkey_get_value,
|
||||
.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)
|
||||
|
|
|
@ -580,6 +580,18 @@ config SYS_I2C_OCTEON
|
|||
chips have several I2C ports and all are provided, controlled by
|
||||
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
|
||||
bool "Samsung I2C driver"
|
||||
depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5) && DM_I2C
|
||||
|
|
|
@ -37,6 +37,7 @@ obj-$(CONFIG_SYS_I2C_NPCM) += npcm_i2c.o
|
|||
obj-$(CONFIG_SYS_I2C_OCORES) += ocores_i2c.o
|
||||
obj-$(CONFIG_SYS_I2C_OCTEON) += octeon_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_IIC) += rcar_iic.o
|
||||
obj-$(CONFIG_SYS_I2C_ROCKCHIP) += rk_i2c.o
|
||||
|
|
579
drivers/i2c/qup_i2c.c
Normal file
579
drivers/i2c/qup_i2c.c
Normal 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,
|
||||
};
|
|
@ -46,6 +46,15 @@ config APPLE_SPI_KEYB
|
|||
laptops based on Apple SoCs. These keyboards use an
|
||||
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
|
||||
bool "Enable Chrome OS EC keyboard support"
|
||||
depends on INPUT
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
obj-$(CONFIG_$(SPL_TPL_)CROS_EC_KEYB) += cros_ec_keyb.o
|
||||
obj-$(CONFIG_$(SPL_TPL_)OF_CONTROL) += key_matrix.o
|
||||
obj-$(CONFIG_$(SPL_TPL_)DM_KEYBOARD) += input.o keyboard-uclass.o
|
||||
obj-$(CONFIG_BUTTON_KEYBOARD) += button_kbd.o
|
||||
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
|
||||
|
|
126
drivers/input/button_kbd.c
Normal file
126
drivers/input/button_kbd.c
Normal 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,
|
||||
};
|
|
@ -242,6 +242,13 @@ config DWC_ETH_QOS_TEGRA186
|
|||
The Synopsys Designware Ethernet QOS IP block with specific
|
||||
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
|
||||
bool "Intel PRO/1000 Gigabit Ethernet support"
|
||||
depends on PCI
|
||||
|
@ -406,6 +413,7 @@ config FSL_FM_10GEC_REGULAR_NOTATION
|
|||
|
||||
config FTMAC100
|
||||
bool "Ftmac100 Ethernet Support"
|
||||
select MII
|
||||
help
|
||||
This MAC is present in Andestech SoCs.
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o
|
|||
obj-$(CONFIG_DSA_SANDBOX) += dsa_sandbox.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_QCOM) += dwc_eth_qos_qcom.o
|
||||
obj-$(CONFIG_E1000) += e1000.o
|
||||
obj-$(CONFIG_E1000_SPI) += e1000_spi.o
|
||||
obj-$(CONFIG_EEPRO100) += eepro100.o
|
||||
|
|
|
@ -774,10 +774,13 @@ static int eqos_start(struct udevice *dev)
|
|||
pr_err("eqos_calibrate_pads() failed: %d", ret);
|
||||
goto err_stop_resets;
|
||||
}
|
||||
rate = eqos->config->ops->eqos_get_tick_clk_rate(dev);
|
||||
|
||||
val = (rate / 1000000) - 1;
|
||||
writel(val, &eqos->mac_regs->us_tic_counter);
|
||||
if (eqos->config->ops->eqos_get_tick_clk_rate) {
|
||||
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,
|
||||
|
@ -849,12 +852,19 @@ static int eqos_start(struct udevice *dev)
|
|||
rx_fifo_sz = (val >> EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_SHIFT) &
|
||||
EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_MASK;
|
||||
|
||||
/*
|
||||
* r/tx_fifo_sz is encoded as log2(n / 128). Undo that by shifting.
|
||||
* r/tqs is encoded as (n / 256) - 1.
|
||||
*/
|
||||
tqs = (128 << tx_fifo_sz) / 256 - 1;
|
||||
rqs = (128 << rx_fifo_sz) / 256 - 1;
|
||||
/* r/tx_fifo_sz is encoded as log2(n / 128). Undo that by shifting */
|
||||
tx_fifo_sz = 128 << tx_fifo_sz;
|
||||
rx_fifo_sz = 128 << rx_fifo_sz;
|
||||
|
||||
/* Allow platform to override TX/RX fifo size */
|
||||
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,
|
||||
EQOS_MTL_TXQ0_OPERATION_MODE_TQS_MASK <<
|
||||
|
@ -1702,6 +1712,13 @@ static const struct udevice_id eqos_ids[] = {
|
|||
},
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_DWC_ETH_QOS_QCOM)
|
||||
{
|
||||
.compatible = "qcom,qcs404-ethqos",
|
||||
.data = (ulong)&eqos_qcom_config
|
||||
},
|
||||
#endif
|
||||
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -253,6 +253,7 @@ struct eqos_priv {
|
|||
struct eqos_mtl_regs *mtl_regs;
|
||||
struct eqos_dma_regs *dma_regs;
|
||||
struct eqos_tegra186_regs *tegra186_regs;
|
||||
void *eqos_qcom_rgmii_regs;
|
||||
struct reset_ctl reset_ctl;
|
||||
struct gpio_desc phy_reset_gpio;
|
||||
struct clk clk_master_bus;
|
||||
|
@ -276,6 +277,8 @@ struct eqos_priv {
|
|||
bool started;
|
||||
bool reg_access_ok;
|
||||
bool clk_ck_enabled;
|
||||
unsigned int tx_fifo_sz, rx_fifo_sz;
|
||||
u32 reset_delays[3];
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
extern struct eqos_config eqos_imx_config;
|
||||
extern struct eqos_config eqos_qcom_config;
|
||||
|
|
612
drivers/net/dwc_eth_qos_qcom.c
Normal file
612
drivers/net/dwc_eth_qos_qcom.c
Normal 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(®s->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(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_CDR_EN);
|
||||
|
||||
/* Set CDR_EXT_EN */
|
||||
setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_CDR_EXT_EN);
|
||||
|
||||
/* Clear CK_OUT_EN */
|
||||
clrbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_CK_OUT_EN);
|
||||
|
||||
/* Set DLL_EN */
|
||||
setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_DLL_EN);
|
||||
|
||||
clrbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_MCLK_GATING_EN);
|
||||
|
||||
clrbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CDR_FINE_PHASE);
|
||||
|
||||
/* Wait for CK_OUT_EN clear */
|
||||
do {
|
||||
val = readl(®s->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(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_CK_OUT_EN);
|
||||
|
||||
/* Wait for CK_OUT_EN set */
|
||||
retry = 1000;
|
||||
do {
|
||||
val = readl(®s->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(®s->sdcc_hc_dll_config2, SDCC_DLL_CONFIG2_DDR_CAL_EN);
|
||||
|
||||
clrbits_le32(®s->sdcc_hc_dll_config2,
|
||||
SDCC_DLL_CONFIG2_DLL_CLOCK_DIS);
|
||||
|
||||
clrsetbits_le32(®s->sdcc_hc_dll_config2,
|
||||
SDCC_DLL_CONFIG2_MCLK_FREQ_CALC, 0x1A << 10);
|
||||
|
||||
clrsetbits_le32(®s->sdcc_hc_dll_config2,
|
||||
SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL, BIT(2));
|
||||
|
||||
setbits_le32(®s->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(®s->io_macro_config2,
|
||||
RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN);
|
||||
|
||||
/* Select RGMII, write 0 to interface select */
|
||||
clrbits_le32(®s->io_macro_config, RGMII_CONFIG_INTF_SEL);
|
||||
|
||||
switch (speed) {
|
||||
case SPEED_1000:
|
||||
setbits_le32(®s->io_macro_config, RGMII_CONFIG_DDR_MODE);
|
||||
clrbits_le32(®s->io_macro_config,
|
||||
RGMII_CONFIG_BYPASS_TX_ID_EN);
|
||||
setbits_le32(®s->io_macro_config,
|
||||
RGMII_CONFIG_POS_NEG_DATA_SEL);
|
||||
setbits_le32(®s->io_macro_config, RGMII_CONFIG_PROG_SWAP);
|
||||
|
||||
clrbits_le32(®s->io_macro_config2,
|
||||
RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL);
|
||||
setbits_le32(®s->io_macro_config2,
|
||||
RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN);
|
||||
clrbits_le32(®s->io_macro_config2,
|
||||
RGMII_CONFIG2_RSVD_CONFIG15);
|
||||
setbits_le32(®s->io_macro_config2,
|
||||
RGMII_CONFIG2_RX_PROG_SWAP);
|
||||
|
||||
/* Set PRG_RCLK_DLY to 57 for 1.8 ns delay */
|
||||
clrsetbits_le32(®s->sdcc_hc_ddr_config,
|
||||
SDCC_DDR_CONFIG_PRG_RCLK_DLY, 57);
|
||||
setbits_le32(®s->sdcc_hc_ddr_config, SDCC_DDR_CONFIG_PRG_DLY_EN);
|
||||
|
||||
setbits_le32(®s->io_macro_config, RGMII_CONFIG_LOOPBACK_EN);
|
||||
break;
|
||||
|
||||
case SPEED_100:
|
||||
setbits_le32(®s->io_macro_config, RGMII_CONFIG_DDR_MODE);
|
||||
setbits_le32(®s->io_macro_config,
|
||||
RGMII_CONFIG_BYPASS_TX_ID_EN);
|
||||
clrbits_le32(®s->io_macro_config,
|
||||
RGMII_CONFIG_POS_NEG_DATA_SEL);
|
||||
clrbits_le32(®s->io_macro_config, RGMII_CONFIG_PROG_SWAP);
|
||||
clrsetbits_le32(®s->io_macro_config,
|
||||
RGMII_CONFIG_MAX_SPD_PRG_2, BIT(6));
|
||||
|
||||
clrbits_le32(®s->io_macro_config2,
|
||||
RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL);
|
||||
setbits_le32(®s->io_macro_config2,
|
||||
RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN);
|
||||
clrbits_le32(®s->io_macro_config2,
|
||||
RGMII_CONFIG2_RSVD_CONFIG15);
|
||||
clrbits_le32(®s->io_macro_config2,
|
||||
RGMII_CONFIG2_RX_PROG_SWAP);
|
||||
|
||||
/* Write 0x5 to PRG_RCLK_DLY_CODE */
|
||||
clrsetbits_le32(®s->sdcc_hc_ddr_config,
|
||||
SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
|
||||
(BIT(29) | BIT(27)));
|
||||
setbits_le32(®s->sdcc_hc_ddr_config,
|
||||
SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY);
|
||||
setbits_le32(®s->sdcc_hc_ddr_config,
|
||||
SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN);
|
||||
|
||||
setbits_le32(®s->io_macro_config, RGMII_CONFIG_LOOPBACK_EN);
|
||||
break;
|
||||
|
||||
case SPEED_10:
|
||||
setbits_le32(®s->io_macro_config, RGMII_CONFIG_DDR_MODE);
|
||||
setbits_le32(®s->io_macro_config,
|
||||
RGMII_CONFIG_BYPASS_TX_ID_EN);
|
||||
clrbits_le32(®s->io_macro_config,
|
||||
RGMII_CONFIG_POS_NEG_DATA_SEL);
|
||||
clrbits_le32(®s->io_macro_config, RGMII_CONFIG_PROG_SWAP);
|
||||
clrsetbits_le32(®s->io_macro_config,
|
||||
RGMII_CONFIG_MAX_SPD_PRG_9,
|
||||
BIT(12) | GENMASK(9, 8));
|
||||
|
||||
clrbits_le32(®s->io_macro_config2,
|
||||
RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL);
|
||||
clrbits_le32(®s->io_macro_config2,
|
||||
RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN);
|
||||
clrbits_le32(®s->io_macro_config2,
|
||||
RGMII_CONFIG2_RSVD_CONFIG15);
|
||||
clrbits_le32(®s->io_macro_config2,
|
||||
RGMII_CONFIG2_RX_PROG_SWAP);
|
||||
|
||||
/* Write 0x5 to PRG_RCLK_DLY_CODE */
|
||||
clrsetbits_le32(®s->sdcc_hc_ddr_config,
|
||||
SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
|
||||
(BIT(29) | BIT(27)));
|
||||
setbits_le32(®s->sdcc_hc_ddr_config,
|
||||
SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY);
|
||||
setbits_le32(®s->sdcc_hc_ddr_config,
|
||||
SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN);
|
||||
|
||||
setbits_le32(®s->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, ®s->io_macro_config);
|
||||
writel(emac_v2_3_0_por.sdcc_hc_dll_config, ®s->sdcc_hc_dll_config);
|
||||
writel(emac_v2_3_0_por.sdcc_hc_ddr_config, ®s->sdcc_hc_ddr_config);
|
||||
writel(emac_v2_3_0_por.sdcc_hc_dll_config2, ®s->sdcc_hc_dll_config2);
|
||||
writel(emac_v2_3_0_por.sdcc_usr_ctl, ®s->sdcc_usr_ctl);
|
||||
writel(emac_v2_3_0_por.io_macro_config2, ®s->io_macro_config2);
|
||||
|
||||
ethqos_set_func_clk_en(regs);
|
||||
|
||||
/* Initialize the DLL first */
|
||||
|
||||
/* Set DLL_RST */
|
||||
setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_DLL_RST);
|
||||
|
||||
/* Set PDN */
|
||||
setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_PDN);
|
||||
|
||||
/* Clear DLL_RST */
|
||||
clrbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_DLL_RST);
|
||||
|
||||
/* Clear PDN */
|
||||
clrbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_PDN);
|
||||
|
||||
if (speed == SPEED_1000) {
|
||||
/* Set DLL_EN */
|
||||
setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_DLL_EN);
|
||||
|
||||
/* Set CK_OUT_EN */
|
||||
setbits_le32(®s->sdcc_hc_dll_config,
|
||||
SDCC_DLL_CONFIG_CK_OUT_EN);
|
||||
|
||||
/* Set USR_CTL bit 26 with mask of 3 bits */
|
||||
clrsetbits_le32(®s->sdcc_usr_ctl, GENMASK(26, 24), BIT(26));
|
||||
|
||||
/* wait for DLL LOCK */
|
||||
do {
|
||||
mdelay(1);
|
||||
if (readl(®s->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(®s->io_macro_config));
|
||||
dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG: %08x\n",
|
||||
readl(®s->sdcc_hc_dll_config));
|
||||
dev_dbg(dev, "SDCC_HC_REG_DDR_CONFIG: %08x\n",
|
||||
readl(®s->sdcc_hc_ddr_config));
|
||||
dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG2: %08x\n",
|
||||
readl(®s->sdcc_hc_dll_config2));
|
||||
dev_dbg(dev, "SDC4_STATUS: %08x\n",
|
||||
readl(®s->sdc4_status));
|
||||
dev_dbg(dev, "SDCC_USR_CTL: %08x\n",
|
||||
readl(®s->sdcc_usr_ctl));
|
||||
dev_dbg(dev, "RGMII_IO_MACRO_CONFIG2: %08x\n",
|
||||
readl(®s->io_macro_config2));
|
||||
dev_dbg(dev, "RGMII_IO_MACRO_DEBUG1: %08x\n",
|
||||
readl(®s->io_macro_debug1));
|
||||
dev_dbg(dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %08x\n",
|
||||
readl(®s->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
|
||||
};
|
|
@ -12,9 +12,13 @@
|
|||
#include <env.h>
|
||||
#include <malloc.h>
|
||||
#include <net.h>
|
||||
#include <phy.h>
|
||||
#include <miiphy.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
||||
#include "ftmac100.h"
|
||||
#include <dm.h>
|
||||
|
@ -23,12 +27,16 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
|
||||
#define ETH_ZLEN 60
|
||||
|
||||
/* Timeout for a mdio read/write operation */
|
||||
#define FTMAC100_MDIO_TIMEOUT_USEC 10000
|
||||
|
||||
struct ftmac100_data {
|
||||
struct ftmac100_txdes txdes[1];
|
||||
struct ftmac100_rxdes rxdes[PKTBUFSRX];
|
||||
int rx_index;
|
||||
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)
|
||||
{
|
||||
struct ftmac100 *ftmac100 = (struct ftmac100 *)(uintptr_t)priv->iobase;
|
||||
struct ftmac100 *ftmac100 = priv->ftmac100;
|
||||
|
||||
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 ,
|
||||
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 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)
|
||||
{
|
||||
struct ftmac100 *ftmac100 = (struct ftmac100 *)(uintptr_t)priv->iobase;
|
||||
struct ftmac100 *ftmac100 = priv->ftmac100;
|
||||
debug ("%s()\n", __func__);
|
||||
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])
|
||||
{
|
||||
struct ftmac100 *ftmac100 = (struct ftmac100 *)(uintptr_t)priv->iobase;
|
||||
struct ftmac100 *ftmac100 = priv->ftmac100;
|
||||
struct ftmac100_txdes *txdes = priv->txdes;
|
||||
struct ftmac100_rxdes *rxdes = priv->rxdes;
|
||||
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)
|
||||
{
|
||||
struct ftmac100 *ftmac100 = (struct ftmac100 *)(uintptr_t)priv->iobase;
|
||||
struct ftmac100 *ftmac100 = priv->ftmac100;
|
||||
struct ftmac100_txdes *curr_des = priv->txdes;
|
||||
ulong start;
|
||||
|
||||
|
@ -314,7 +322,7 @@ static int ftmac100_of_to_plat(struct udevice *dev)
|
|||
struct eth_pdata *pdata = dev_get_plat(dev);
|
||||
const char *mac;
|
||||
pdata->iobase = dev_read_addr(dev);
|
||||
priv->iobase = pdata->iobase;
|
||||
priv->ftmac100 = phys_to_virt(pdata->iobase);
|
||||
mac = dtbmacaddr(0);
|
||||
if (mac)
|
||||
memcpy(pdata->enetaddr , mac , 6);
|
||||
|
@ -322,10 +330,104 @@ static int ftmac100_of_to_plat(struct udevice *dev)
|
|||
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)
|
||||
{
|
||||
struct ftmac100_data *priv = dev_get_priv(dev);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -348,12 +450,13 @@ static const struct udevice_id ftmac100_ids[] = {
|
|||
};
|
||||
|
||||
U_BOOT_DRIVER(ftmac100) = {
|
||||
.name = "nds32_mac",
|
||||
.name = "ftmac100",
|
||||
.id = UCLASS_ETH,
|
||||
.of_match = ftmac100_ids,
|
||||
.bind = ftmac100_bind,
|
||||
.of_to_plat = ftmac100_of_to_plat,
|
||||
.probe = ftmac100_probe,
|
||||
.remove = ftmac100_remove,
|
||||
.ops = &ftmac100_ops,
|
||||
.priv_auto = sizeof(struct ftmac100_data),
|
||||
.plat_auto = sizeof(struct eth_pdata),
|
||||
|
|
|
@ -92,6 +92,15 @@ struct ftmac100 {
|
|||
#define FTMAC100_MACCR_RX_MULTIPKT (1 << 16)
|
||||
#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
|
||||
*/
|
||||
|
|
1
env/Kconfig
vendored
1
env/Kconfig
vendored
|
@ -733,6 +733,7 @@ config ENV_APPEND
|
|||
|
||||
config ENV_WRITEABLE_LIST
|
||||
bool "Permit write access only to listed variables"
|
||||
select ENV_APPEND
|
||||
help
|
||||
If defined, only environment variables which explicitly set the 'w'
|
||||
writeable flag can be written and modified at runtime. No variables
|
||||
|
|
8
env/env.c
vendored
8
env/env.c
vendored
|
@ -192,6 +192,14 @@ int env_load(void)
|
|||
int best_prio = -1;
|
||||
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++) {
|
||||
int ret;
|
||||
|
||||
|
|
10
env/flags.c
vendored
10
env/flags.c
vendored
|
@ -22,7 +22,7 @@
|
|||
#include <env_internal.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CMD_NET
|
||||
#ifdef CONFIG_NET
|
||||
#define ENV_FLAGS_NET_VARTYPE_REPS "im"
|
||||
#else
|
||||
#define ENV_FLAGS_NET_VARTYPE_REPS ""
|
||||
|
@ -57,7 +57,7 @@ static const char * const env_flags_vartype_names[] = {
|
|||
"decimal",
|
||||
"hexadecimal",
|
||||
"boolean",
|
||||
#ifdef CONFIG_CMD_NET
|
||||
#ifdef CONFIG_NET
|
||||
"IP address",
|
||||
"MAC address",
|
||||
#endif
|
||||
|
@ -211,7 +211,7 @@ static void skip_num(int hex, const char *value, const char **end,
|
|||
*end = value;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CMD_NET
|
||||
#ifdef CONFIG_NET
|
||||
int eth_validate_ethaddr_str(const char *addr)
|
||||
{
|
||||
const char *end;
|
||||
|
@ -244,7 +244,7 @@ static int _env_flags_validate_type(const char *value,
|
|||
enum env_flags_vartype type)
|
||||
{
|
||||
const char *end;
|
||||
#ifdef CONFIG_CMD_NET
|
||||
#ifdef CONFIG_NET
|
||||
const char *cur;
|
||||
int i;
|
||||
#endif
|
||||
|
@ -273,7 +273,7 @@ static int _env_flags_validate_type(const char *value,
|
|||
if (value[1] != '\0')
|
||||
return -1;
|
||||
break;
|
||||
#ifdef CONFIG_CMD_NET
|
||||
#ifdef CONFIG_NET
|
||||
case env_flags_vartype_ipaddr:
|
||||
cur = value;
|
||||
for (i = 0; i < 4; i++) {
|
||||
|
|
|
@ -37,6 +37,14 @@ struct button_ops {
|
|||
* @return button state button_state_t, or -ve on error
|
||||
*/
|
||||
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)
|
||||
|
@ -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);
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
#ifndef __CONFIG_H
|
||||
#define __CONFIG_H
|
||||
|
||||
#define CFG_SYS_NS16550_COM1 0xf040c000
|
||||
|
||||
#define CFG_SYS_INIT_RAM_ADDR 0x10200000
|
||||
|
||||
#include "bcmstb.h"
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
#ifndef __CONFIG_H
|
||||
#define __CONFIG_H
|
||||
|
||||
#define CFG_SYS_NS16550_COM1 0xf040ab00
|
||||
|
||||
#define CFG_SYS_INIT_RAM_ADDR 0x80200000
|
||||
|
||||
#include "bcmstb.h"
|
||||
|
|
|
@ -92,19 +92,6 @@ extern phys_addr_t prior_stage_fdt_address;
|
|||
* 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.
|
||||
*/
|
||||
|
|
|
@ -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
|
|
@ -12,7 +12,7 @@ enum env_flags_vartype {
|
|||
env_flags_vartype_decimal,
|
||||
env_flags_vartype_hex,
|
||||
env_flags_vartype_bool,
|
||||
#ifdef CONFIG_CMD_NET
|
||||
#ifdef CONFIG_NET
|
||||
env_flags_vartype_ipaddr,
|
||||
env_flags_vartype_macaddr,
|
||||
#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);
|
||||
|
||||
#ifdef CONFIG_CMD_NET
|
||||
#ifdef CONFIG_NET
|
||||
/*
|
||||
* Check if a string has the format of an Ethernet MAC address
|
||||
*/
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <power/sandbox_pmic.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <dm/test.h>
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <test/ut.h>
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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 */
|
||||
static int dm_test_button_keys_adc(struct unit_test_state *uts)
|
||||
{
|
||||
|
|
|
@ -1046,7 +1046,7 @@ static int dm_test_ofnode_for_each_prop(struct unit_test_state *uts)
|
|||
struct ofprop prop;
|
||||
int count;
|
||||
|
||||
node = ofnode_path("/buttons");
|
||||
node = ofnode_path("/ofnode-foreach");
|
||||
count = 0;
|
||||
|
||||
/* we expect "compatible" for each node */
|
||||
|
|
Loading…
Reference in a new issue