From 39fbb56f845431686966a90456bd232f0b355dbd Mon Sep 17 00:00:00 2001 From: Kever Yang Date: Wed, 28 Dec 2016 11:32:35 +0800 Subject: mmc: rockchip_sdhci: add clock init for mmc Init the clock rate to max-frequency from dts with clock driver api. Signed-off-by: Kever Yang Reviewed-by: Jaehoon Chung --- drivers/mmc/rockchip_sdhci.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index c56e1a3..e33e35e 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -12,7 +12,9 @@ #include #include #include +#include +DECLARE_GLOBAL_DATA_PTR; /* 400KHz is max freq for card ID etc. Use that as min */ #define EMMC_MIN_FREQ 400000 @@ -32,11 +34,24 @@ static int arasan_sdhci_probe(struct udevice *dev) struct rockchip_sdhc_plat *plat = dev_get_platdata(dev); struct rockchip_sdhc *prv = dev_get_priv(dev); struct sdhci_host *host = &prv->host; - int ret; + int max_frequency, ret; + struct clk clk; + + + max_frequency = fdtdec_get_int(gd->fdt_blob, dev->of_offset, + "max-frequency", 0); + ret = clk_get_by_index(dev, 0, &clk); + if (!ret) { + ret = clk_set_rate(&clk, max_frequency); + if (IS_ERR_VALUE(ret)) + printf("%s clk set rate fail!\n", __func__); + } else { + printf("%s fail to get clk\n", __func__); + } host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD; - ret = sdhci_setup_cfg(&plat->cfg, host, CONFIG_ROCKCHIP_SDHCI_MAX_FREQ, + ret = sdhci_setup_cfg(&plat->cfg, host, max_frequency, EMMC_MIN_FREQ); host->mmc = &plat->mmc; -- cgit v1.1 From 0fc41e551eebe9b745961083c5961509b9bab240 Mon Sep 17 00:00:00 2001 From: Nickey Yang Nickey Yang Date: Thu, 29 Dec 2016 14:01:26 +0800 Subject: rockchip: video: fix mpixelclock in rockchip HDMI Correct mpixelclock errors in rockchip_phy_config[] and rockchip_mpll_cfg[]. Signed-off-by: Nickey Yang --- drivers/video/rockchip/rk_hdmi.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/video/rockchip/rk_hdmi.c b/drivers/video/rockchip/rk_hdmi.c index 032b1de..1a4fa36 100644 --- a/drivers/video/rockchip/rk_hdmi.c +++ b/drivers/video/rockchip/rk_hdmi.c @@ -85,13 +85,13 @@ struct hdmi_phy_config { static const struct hdmi_phy_config rockchip_phy_config[] = { { - .mpixelclock = 74250, + .mpixelclock = 74250000, .sym_ctr = 0x8009, .term = 0x0004, .vlev_ctr = 0x0272, }, { - .mpixelclock = 148500, + .mpixelclock = 148500000, .sym_ctr = 0x802b, .term = 0x0004, .vlev_ctr = 0x028d, }, { - .mpixelclock = 297000, + .mpixelclock = 297000000, .sym_ctr = 0x8039, .term = 0x0005, .vlev_ctr = 0x028d, }, { .mpixelclock = ~0ul, @@ -101,22 +101,22 @@ static const struct hdmi_phy_config rockchip_phy_config[] = { static const struct hdmi_mpll_config rockchip_mpll_cfg[] = { { - .mpixelclock = 40000, + .mpixelclock = 40000000, .cpce = 0x00b3, .gmp = 0x0000, .curr = 0x0018, }, { - .mpixelclock = 65000, + .mpixelclock = 65000000, .cpce = 0x0072, .gmp = 0x0001, .curr = 0x0028, }, { - .mpixelclock = 66000, + .mpixelclock = 66000000, .cpce = 0x013e, .gmp = 0x0003, .curr = 0x0038, }, { - .mpixelclock = 83500, + .mpixelclock = 835000000, .cpce = 0x0072, .gmp = 0x0001, .curr = 0x0028, }, { - .mpixelclock = 146250, + .mpixelclock = 146250000, .cpce = 0x0051, .gmp = 0x0002, .curr = 0x0038, }, { - .mpixelclock = 148500, + .mpixelclock = 148500000, .cpce = 0x0051, .gmp = 0x0003, .curr = 0x0000, }, { .mpixelclock = ~0ul, @@ -870,7 +870,7 @@ static int rk_hdmi_probe(struct udevice *dev) clk_free(&clk); } if (ret) { - debug("%s: Failed to set EDP clock: ret=%d\n", __func__, ret); + debug("%s: Failed to set hdmi clock: ret=%d\n", __func__, ret); return ret; } -- cgit v1.1 From b9e08d0e80e311591704a49341199637069fd157 Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Wed, 11 Jan 2017 11:46:07 +0100 Subject: net: designware: Export various functions/struct to allow subclassing To allow other DM drivers to subclass the designware driver various functions and structures need to be exported. Export these. Signed-off-by: Sjoerd Simons Signed-off-by: Romain Perier Reviewed-by: Bin Meng Acked-by: Simon Glass Acked-by: Joe Hershberger --- drivers/net/designware.c | 6 +++--- drivers/net/designware.h | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 9e6d726..6ef36bc 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -628,7 +628,7 @@ static int designware_eth_bind(struct udevice *dev) return 0; } -static int designware_eth_probe(struct udevice *dev) +int designware_eth_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); struct dw_eth_dev *priv = dev_get_priv(dev); @@ -678,7 +678,7 @@ static int designware_eth_remove(struct udevice *dev) return 0; } -static const struct eth_ops designware_eth_ops = { +const struct eth_ops designware_eth_ops = { .start = designware_eth_start, .send = designware_eth_send, .recv = designware_eth_recv, @@ -687,7 +687,7 @@ static const struct eth_ops designware_eth_ops = { .write_hwaddr = designware_eth_write_hwaddr, }; -static int designware_eth_ofdata_to_platdata(struct udevice *dev) +int designware_eth_ofdata_to_platdata(struct udevice *dev) { struct dw_eth_pdata *dw_pdata = dev_get_platdata(dev); #ifdef CONFIG_DM_GPIO diff --git a/drivers/net/designware.h b/drivers/net/designware.h index d345c5b..087ebef 100644 --- a/drivers/net/designware.h +++ b/drivers/net/designware.h @@ -245,6 +245,10 @@ struct dw_eth_dev { }; #ifdef CONFIG_DM_ETH +int designware_eth_ofdata_to_platdata(struct udevice *dev); +int designware_eth_probe(struct udevice *dev); +extern const struct eth_ops designware_eth_ops; + struct dw_eth_pdata { struct eth_pdata eth_pdata; u32 reset_delays[3]; -- cgit v1.1 From 0ea38db90caa55e8366c9bef4214ab52b3fedf6a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 11 Jan 2017 11:46:08 +0100 Subject: net: designware: Adjust dw_adjust_link() to return an error This function can fail, so return the error if there is one. Signed-off-by: Simon Glass Signed-off-by: Romain Perier Acked-by: Joe Hershberger --- drivers/net/designware.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 6ef36bc..ebcef8b 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -230,14 +230,14 @@ static int _dw_write_hwaddr(struct dw_eth_dev *priv, u8 *mac_id) return 0; } -static void dw_adjust_link(struct eth_mac_regs *mac_p, - struct phy_device *phydev) +static int dw_adjust_link(struct dw_eth_dev *priv, struct eth_mac_regs *mac_p, + struct phy_device *phydev) { u32 conf = readl(&mac_p->conf) | FRAMEBURSTENABLE | DISABLERXOWN; if (!phydev->link) { printf("%s: No link.\n", phydev->dev->name); - return; + return 0; } if (phydev->speed != 1000) @@ -256,6 +256,8 @@ static void dw_adjust_link(struct eth_mac_regs *mac_p, printf("Speed: %d, %s duplex%s\n", phydev->speed, (phydev->duplex) ? "full" : "half", (phydev->port == PORT_FIBRE) ? ", fiber mode" : ""); + + return 0; } static void _dw_eth_halt(struct dw_eth_dev *priv) @@ -321,7 +323,9 @@ static int _dw_eth_init(struct dw_eth_dev *priv, u8 *enetaddr) return ret; } - dw_adjust_link(mac_p, priv->phydev); + ret = dw_adjust_link(priv, mac_p, priv->phydev); + if (ret) + return ret; if (!priv->phydev->link) return -EIO; -- cgit v1.1 From f63f28ee2520263f5c78f64f1d404b2c329ffe87 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 11 Jan 2017 11:46:09 +0100 Subject: net: designware: Split the link init into a separate function With rockchip we need to make adjustments after the link speed is set but before enabling received/transmit. In preparation for this, split these two pieces into separate functions. Signed-off-by: Simon Glass Signed-off-by: Romain Perier Acked-by: Joe Hershberger --- drivers/net/designware.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/designware.c b/drivers/net/designware.c index ebcef8b..0c596a7 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -327,6 +327,13 @@ static int _dw_eth_init(struct dw_eth_dev *priv, u8 *enetaddr) if (ret) return ret; + return 0; +} + +static int designware_eth_enable(struct dw_eth_dev *priv) +{ + struct eth_mac_regs *mac_p = priv->mac_regs_p; + if (!priv->phydev->link) return -EIO; @@ -484,7 +491,13 @@ static int dw_phy_init(struct dw_eth_dev *priv, void *dev) #ifndef CONFIG_DM_ETH static int dw_eth_init(struct eth_device *dev, bd_t *bis) { - return _dw_eth_init(dev->priv, dev->enetaddr); + int ret; + + ret = _dw_eth_init(dev->priv, dev->enetaddr); + if (!ret) + ret = designware_eth_enable(dev->priv); + + return ret; } static int dw_eth_send(struct eth_device *dev, void *packet, int length) @@ -575,8 +588,17 @@ int designware_initialize(ulong base_addr, u32 interface) static int designware_eth_start(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); + struct dw_eth_dev *priv = dev_get_priv(dev); + int ret; - return _dw_eth_init(dev->priv, pdata->enetaddr); + ret = _dw_eth_init(priv, pdata->enetaddr); + if (ret) + return ret; + ret = designware_eth_enable(priv); + if (ret) + return ret; + + return 0; } static int designware_eth_send(struct udevice *dev, void *packet, int length) -- cgit v1.1 From e72ced234045f817df48cec71b4795b00e87afe3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 11 Jan 2017 11:46:10 +0100 Subject: net: designware: Export the operation functions Export all functions so that drivers can use them, or not, as the need arises. Signed-off-by: Simon Glass Signed-off-by: Romain Perier Acked-by: Joe Hershberger --- drivers/net/designware.c | 19 +++++++++---------- drivers/net/designware.h | 9 +++++++++ 2 files changed, 18 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 0c596a7..f242fc6 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -271,7 +271,7 @@ static void _dw_eth_halt(struct dw_eth_dev *priv) phy_shutdown(priv->phydev); } -static int _dw_eth_init(struct dw_eth_dev *priv, u8 *enetaddr) +int designware_eth_init(struct dw_eth_dev *priv, u8 *enetaddr) { struct eth_mac_regs *mac_p = priv->mac_regs_p; struct eth_dma_regs *dma_p = priv->dma_regs_p; @@ -330,7 +330,7 @@ static int _dw_eth_init(struct dw_eth_dev *priv, u8 *enetaddr) return 0; } -static int designware_eth_enable(struct dw_eth_dev *priv) +int designware_eth_enable(struct dw_eth_dev *priv) { struct eth_mac_regs *mac_p = priv->mac_regs_p; @@ -493,7 +493,7 @@ static int dw_eth_init(struct eth_device *dev, bd_t *bis) { int ret; - ret = _dw_eth_init(dev->priv, dev->enetaddr); + ret = designware_eth_init(dev->priv, dev->enetaddr); if (!ret) ret = designware_eth_enable(dev->priv); @@ -591,7 +591,7 @@ static int designware_eth_start(struct udevice *dev) struct dw_eth_dev *priv = dev_get_priv(dev); int ret; - ret = _dw_eth_init(priv, pdata->enetaddr); + ret = designware_eth_init(priv, pdata->enetaddr); if (ret) return ret; ret = designware_eth_enable(priv); @@ -601,36 +601,35 @@ static int designware_eth_start(struct udevice *dev) return 0; } -static int designware_eth_send(struct udevice *dev, void *packet, int length) +int designware_eth_send(struct udevice *dev, void *packet, int length) { struct dw_eth_dev *priv = dev_get_priv(dev); return _dw_eth_send(priv, packet, length); } -static int designware_eth_recv(struct udevice *dev, int flags, uchar **packetp) +int designware_eth_recv(struct udevice *dev, int flags, uchar **packetp) { struct dw_eth_dev *priv = dev_get_priv(dev); return _dw_eth_recv(priv, packetp); } -static int designware_eth_free_pkt(struct udevice *dev, uchar *packet, - int length) +int designware_eth_free_pkt(struct udevice *dev, uchar *packet, int length) { struct dw_eth_dev *priv = dev_get_priv(dev); return _dw_free_pkt(priv); } -static void designware_eth_stop(struct udevice *dev) +void designware_eth_stop(struct udevice *dev) { struct dw_eth_dev *priv = dev_get_priv(dev); return _dw_eth_halt(priv); } -static int designware_eth_write_hwaddr(struct udevice *dev) +int designware_eth_write_hwaddr(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); struct dw_eth_dev *priv = dev_get_priv(dev); diff --git a/drivers/net/designware.h b/drivers/net/designware.h index 087ebef..7992d0e 100644 --- a/drivers/net/designware.h +++ b/drivers/net/designware.h @@ -253,6 +253,15 @@ struct dw_eth_pdata { struct eth_pdata eth_pdata; u32 reset_delays[3]; }; + +int designware_eth_init(struct dw_eth_dev *priv, u8 *enetaddr); +int designware_eth_enable(struct dw_eth_dev *priv); +int designware_eth_send(struct udevice *dev, void *packet, int length); +int designware_eth_recv(struct udevice *dev, int flags, uchar **packetp); +int designware_eth_free_pkt(struct udevice *dev, uchar *packet, + int length); +void designware_eth_stop(struct udevice *dev); +int designware_eth_write_hwaddr(struct udevice *dev); #endif #endif -- cgit v1.1 From 0125bcf01cfb0715b35ab9d5325479b3953bb966 Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Wed, 11 Jan 2017 11:46:11 +0100 Subject: net: gmac_rockchip: Add Rockchip GMAC driver Add a new driver for the GMAC ethernet interface present in Rockchip RK3288 SOCs. This driver subclasses the generic design-ware driver to add the glue needed specifically for Rockchip. Signed-off-by: Sjoerd Simons Signed-off-by: Simon Glass Signed-off-by: Romain Perier Acked-by: Joe Hershberger --- drivers/net/Kconfig | 7 ++ drivers/net/Makefile | 1 + drivers/net/gmac_rockchip.c | 154 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 162 insertions(+) create mode 100644 drivers/net/gmac_rockchip.c (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 929b9e2..f52629f 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -215,4 +215,11 @@ config PIC32_ETH This driver implements 10/100 Mbps Ethernet and MAC layer for Microchip PIC32 microcontrollers. +config GMAC_ROCKCHIP + bool "Rockchip Synopsys Designware Ethernet MAC" + depends on DM_ETH && ETH_DESIGNWARE + help + This driver provides Rockchip SoCs network support based on the + Synopsys Designware driver. + endif # NETDEVICES diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 9a7bfc6..2493a48 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_FTGMAC100) += ftgmac100.o obj-$(CONFIG_FTMAC110) += ftmac110.o obj-$(CONFIG_FTMAC100) += ftmac100.o obj-$(CONFIG_GRETH) += greth.o +obj-$(CONFIG_GMAC_ROCKCHIP) += gmac_rockchip.o obj-$(CONFIG_DRIVER_TI_KEYSTONE_NET) += keystone_net.o obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o obj-$(CONFIG_LAN91C96) += lan91c96.o diff --git a/drivers/net/gmac_rockchip.c b/drivers/net/gmac_rockchip.c new file mode 100644 index 0000000..5f833fa --- /dev/null +++ b/drivers/net/gmac_rockchip.c @@ -0,0 +1,154 @@ +/* + * (C) Copyright 2015 Sjoerd Simons + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Rockchip GMAC ethernet IP driver for U-Boot + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "designware.h" + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Platform data for the gmac + * + * dw_eth_pdata: Required platform data for designware driver (must be first) + */ +struct gmac_rockchip_platdata { + struct dw_eth_pdata dw_eth_pdata; + int tx_delay; + int rx_delay; +}; + +static int gmac_rockchip_ofdata_to_platdata(struct udevice *dev) +{ + struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev); + + pdata->tx_delay = fdtdec_get_int(gd->fdt_blob, dev->of_offset, + "tx-delay", 0x30); + pdata->rx_delay = fdtdec_get_int(gd->fdt_blob, dev->of_offset, + "rx-delay", 0x10); + + return designware_eth_ofdata_to_platdata(dev); +} + +static int gmac_rockchip_fix_mac_speed(struct dw_eth_dev *priv) +{ + struct rk3288_grf *grf; + int clk; + + switch (priv->phydev->speed) { + case 10: + clk = GMAC_CLK_SEL_2_5M; + break; + case 100: + clk = GMAC_CLK_SEL_25M; + break; + case 1000: + clk = GMAC_CLK_SEL_125M; + break; + default: + debug("Unknown phy speed: %d\n", priv->phydev->speed); + return -EINVAL; + } + + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + rk_clrsetreg(&grf->soc_con1, + GMAC_CLK_SEL_MASK << GMAC_CLK_SEL_SHIFT, + clk << GMAC_CLK_SEL_SHIFT); + + return 0; +} + +static int gmac_rockchip_probe(struct udevice *dev) +{ + struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev); + struct rk3288_grf *grf; + struct clk clk; + int ret; + + ret = clk_get_by_index(dev, 0, &clk); + if (ret) + return ret; + + /* Since mac_clk is fed by an external clock we can use 0 here */ + ret = clk_set_rate(&clk, 0); + if (ret) + return ret; + + /* Set to RGMII mode */ + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + rk_clrsetreg(&grf->soc_con1, + RMII_MODE_MASK << RMII_MODE_SHIFT | + GMAC_PHY_INTF_SEL_MASK << GMAC_PHY_INTF_SEL_SHIFT, + GMAC_PHY_INTF_SEL_RGMII << GMAC_PHY_INTF_SEL_SHIFT); + + rk_clrsetreg(&grf->soc_con3, + RXCLK_DLY_ENA_GMAC_MASK << RXCLK_DLY_ENA_GMAC_SHIFT | + TXCLK_DLY_ENA_GMAC_MASK << TXCLK_DLY_ENA_GMAC_SHIFT | + CLK_RX_DL_CFG_GMAC_MASK << CLK_RX_DL_CFG_GMAC_SHIFT | + CLK_TX_DL_CFG_GMAC_MASK << CLK_TX_DL_CFG_GMAC_SHIFT, + RXCLK_DLY_ENA_GMAC_ENABLE << RXCLK_DLY_ENA_GMAC_SHIFT | + TXCLK_DLY_ENA_GMAC_ENABLE << TXCLK_DLY_ENA_GMAC_SHIFT | + pdata->rx_delay << CLK_RX_DL_CFG_GMAC_SHIFT | + pdata->tx_delay << CLK_TX_DL_CFG_GMAC_SHIFT); + + return designware_eth_probe(dev); +} + +static int gmac_rockchip_eth_start(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + struct dw_eth_dev *priv = dev_get_priv(dev); + int ret; + + ret = designware_eth_init(priv, pdata->enetaddr); + if (ret) + return ret; + ret = gmac_rockchip_fix_mac_speed(priv); + if (ret) + return ret; + ret = designware_eth_enable(priv); + if (ret) + return ret; + + return 0; +} + +const struct eth_ops gmac_rockchip_eth_ops = { + .start = gmac_rockchip_eth_start, + .send = designware_eth_send, + .recv = designware_eth_recv, + .free_pkt = designware_eth_free_pkt, + .stop = designware_eth_stop, + .write_hwaddr = designware_eth_write_hwaddr, +}; + +static const struct udevice_id rockchip_gmac_ids[] = { + { .compatible = "rockchip,rk3288-gmac" }, + { } +}; + +U_BOOT_DRIVER(eth_gmac_rockchip) = { + .name = "gmac_rockchip", + .id = UCLASS_ETH, + .of_match = rockchip_gmac_ids, + .ofdata_to_platdata = gmac_rockchip_ofdata_to_platdata, + .probe = gmac_rockchip_probe, + .ops = &gmac_rockchip_eth_ops, + .priv_auto_alloc_size = sizeof(struct dw_eth_dev), + .platdata_auto_alloc_size = sizeof(struct gmac_rockchip_platdata), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; -- cgit v1.1