cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bgmac-platform.c (7876B)


      1/*
      2 * Copyright (C) 2016 Broadcom
      3 *
      4 * This program is free software; you can redistribute it and/or
      5 * modify it under the terms of the GNU General Public License as
      6 * published by the Free Software Foundation version 2.
      7 *
      8 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
      9 * kind, whether express or implied; without even the implied warranty
     10 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11 * GNU General Public License for more details.
     12 */
     13
     14#define pr_fmt(fmt)		KBUILD_MODNAME ": " fmt
     15
     16#include <linux/bcma/bcma.h>
     17#include <linux/brcmphy.h>
     18#include <linux/etherdevice.h>
     19#include <linux/of_address.h>
     20#include <linux/of_mdio.h>
     21#include <linux/of_net.h>
     22#include "bgmac.h"
     23
     24#define NICPM_PADRING_CFG		0x00000004
     25#define NICPM_IOMUX_CTRL		0x00000008
     26
     27#define NICPM_PADRING_CFG_INIT_VAL	0x74000000
     28#define NICPM_IOMUX_CTRL_INIT_VAL_AX	0x21880000
     29
     30#define NICPM_IOMUX_CTRL_INIT_VAL	0x3196e000
     31#define NICPM_IOMUX_CTRL_SPD_SHIFT	10
     32#define NICPM_IOMUX_CTRL_SPD_10M	0
     33#define NICPM_IOMUX_CTRL_SPD_100M	1
     34#define NICPM_IOMUX_CTRL_SPD_1000M	2
     35
     36static u32 platform_bgmac_read(struct bgmac *bgmac, u16 offset)
     37{
     38	return readl(bgmac->plat.base + offset);
     39}
     40
     41static void platform_bgmac_write(struct bgmac *bgmac, u16 offset, u32 value)
     42{
     43	writel(value, bgmac->plat.base + offset);
     44}
     45
     46static u32 platform_bgmac_idm_read(struct bgmac *bgmac, u16 offset)
     47{
     48	return readl(bgmac->plat.idm_base + offset);
     49}
     50
     51static void platform_bgmac_idm_write(struct bgmac *bgmac, u16 offset, u32 value)
     52{
     53	writel(value, bgmac->plat.idm_base + offset);
     54}
     55
     56static bool platform_bgmac_clk_enabled(struct bgmac *bgmac)
     57{
     58	if (!bgmac->plat.idm_base)
     59		return true;
     60
     61	if ((bgmac_idm_read(bgmac, BCMA_IOCTL) & BGMAC_CLK_EN) != BGMAC_CLK_EN)
     62		return false;
     63	if (bgmac_idm_read(bgmac, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET)
     64		return false;
     65	return true;
     66}
     67
     68static void platform_bgmac_clk_enable(struct bgmac *bgmac, u32 flags)
     69{
     70	u32 val;
     71
     72	if (!bgmac->plat.idm_base)
     73		return;
     74
     75	/* The Reset Control register only contains a single bit to show if the
     76	 * controller is currently in reset.  Do a sanity check here, just in
     77	 * case the bootloader happened to leave the device in reset.
     78	 */
     79	val = bgmac_idm_read(bgmac, BCMA_RESET_CTL);
     80	if (val) {
     81		bgmac_idm_write(bgmac, BCMA_RESET_CTL, 0);
     82		bgmac_idm_read(bgmac, BCMA_RESET_CTL);
     83		udelay(1);
     84	}
     85
     86	val = bgmac_idm_read(bgmac, BCMA_IOCTL);
     87	/* Some bits of BCMA_IOCTL set by HW/ATF and should not change */
     88	val |= flags & ~(BGMAC_AWCACHE | BGMAC_ARCACHE | BGMAC_AWUSER |
     89			 BGMAC_ARUSER);
     90	val |= BGMAC_CLK_EN;
     91	bgmac_idm_write(bgmac, BCMA_IOCTL, val);
     92	bgmac_idm_read(bgmac, BCMA_IOCTL);
     93	udelay(1);
     94}
     95
     96static void platform_bgmac_cco_ctl_maskset(struct bgmac *bgmac, u32 offset,
     97					   u32 mask, u32 set)
     98{
     99	/* This shouldn't be encountered */
    100	WARN_ON(1);
    101}
    102
    103static u32 platform_bgmac_get_bus_clock(struct bgmac *bgmac)
    104{
    105	/* This shouldn't be encountered */
    106	WARN_ON(1);
    107
    108	return 0;
    109}
    110
    111static void platform_bgmac_cmn_maskset32(struct bgmac *bgmac, u16 offset,
    112					 u32 mask, u32 set)
    113{
    114	/* This shouldn't be encountered */
    115	WARN_ON(1);
    116}
    117
    118static void bgmac_nicpm_speed_set(struct net_device *net_dev)
    119{
    120	struct bgmac *bgmac = netdev_priv(net_dev);
    121	u32 val;
    122
    123	if (!bgmac->plat.nicpm_base)
    124		return;
    125
    126	/* SET RGMII IO CONFIG */
    127	writel(NICPM_PADRING_CFG_INIT_VAL,
    128	       bgmac->plat.nicpm_base + NICPM_PADRING_CFG);
    129
    130	val = NICPM_IOMUX_CTRL_INIT_VAL;
    131	switch (bgmac->net_dev->phydev->speed) {
    132	default:
    133		netdev_err(net_dev, "Unsupported speed. Defaulting to 1000Mb\n");
    134		fallthrough;
    135	case SPEED_1000:
    136		val |= NICPM_IOMUX_CTRL_SPD_1000M << NICPM_IOMUX_CTRL_SPD_SHIFT;
    137		break;
    138	case SPEED_100:
    139		val |= NICPM_IOMUX_CTRL_SPD_100M << NICPM_IOMUX_CTRL_SPD_SHIFT;
    140		break;
    141	case SPEED_10:
    142		val |= NICPM_IOMUX_CTRL_SPD_10M << NICPM_IOMUX_CTRL_SPD_SHIFT;
    143		break;
    144	}
    145
    146	writel(val, bgmac->plat.nicpm_base + NICPM_IOMUX_CTRL);
    147
    148	bgmac_adjust_link(bgmac->net_dev);
    149}
    150
    151static int platform_phy_connect(struct bgmac *bgmac)
    152{
    153	struct phy_device *phy_dev;
    154
    155	if (bgmac->plat.nicpm_base)
    156		phy_dev = of_phy_get_and_connect(bgmac->net_dev,
    157						 bgmac->dev->of_node,
    158						 bgmac_nicpm_speed_set);
    159	else
    160		phy_dev = of_phy_get_and_connect(bgmac->net_dev,
    161						 bgmac->dev->of_node,
    162						 bgmac_adjust_link);
    163	if (!phy_dev) {
    164		dev_err(bgmac->dev, "PHY connection failed\n");
    165		return -ENODEV;
    166	}
    167
    168	return 0;
    169}
    170
    171static int bgmac_probe(struct platform_device *pdev)
    172{
    173	struct device_node *np = pdev->dev.of_node;
    174	struct bgmac *bgmac;
    175	struct resource *regs;
    176	int ret;
    177
    178	bgmac = bgmac_alloc(&pdev->dev);
    179	if (!bgmac)
    180		return -ENOMEM;
    181
    182	platform_set_drvdata(pdev, bgmac);
    183
    184	/* Set the features of the 4707 family */
    185	bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
    186	bgmac->feature_flags |= BGMAC_FEAT_NO_RESET;
    187	bgmac->feature_flags |= BGMAC_FEAT_CMDCFG_SR_REV4;
    188	bgmac->feature_flags |= BGMAC_FEAT_TX_MASK_SETUP;
    189	bgmac->feature_flags |= BGMAC_FEAT_RX_MASK_SETUP;
    190	bgmac->feature_flags |= BGMAC_FEAT_IDM_MASK;
    191
    192	bgmac->dev = &pdev->dev;
    193	bgmac->dma_dev = &pdev->dev;
    194
    195	ret = of_get_ethdev_address(np, bgmac->net_dev);
    196	if (ret == -EPROBE_DEFER)
    197		return ret;
    198
    199	if (ret)
    200		dev_warn(&pdev->dev,
    201			 "MAC address not present in device tree\n");
    202
    203	bgmac->irq = platform_get_irq(pdev, 0);
    204	if (bgmac->irq < 0)
    205		return bgmac->irq;
    206
    207	bgmac->plat.base =
    208		devm_platform_ioremap_resource_byname(pdev, "amac_base");
    209	if (IS_ERR(bgmac->plat.base))
    210		return PTR_ERR(bgmac->plat.base);
    211
    212	/* The idm_base resource is optional for some platforms */
    213	regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "idm_base");
    214	if (regs) {
    215		bgmac->plat.idm_base = devm_ioremap_resource(&pdev->dev, regs);
    216		if (IS_ERR(bgmac->plat.idm_base))
    217			return PTR_ERR(bgmac->plat.idm_base);
    218		bgmac->feature_flags &= ~BGMAC_FEAT_IDM_MASK;
    219	}
    220
    221	/* The nicpm_base resource is optional for some platforms */
    222	regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nicpm_base");
    223	if (regs) {
    224		bgmac->plat.nicpm_base = devm_ioremap_resource(&pdev->dev,
    225							       regs);
    226		if (IS_ERR(bgmac->plat.nicpm_base))
    227			return PTR_ERR(bgmac->plat.nicpm_base);
    228	}
    229
    230	bgmac->read = platform_bgmac_read;
    231	bgmac->write = platform_bgmac_write;
    232	bgmac->idm_read = platform_bgmac_idm_read;
    233	bgmac->idm_write = platform_bgmac_idm_write;
    234	bgmac->clk_enabled = platform_bgmac_clk_enabled;
    235	bgmac->clk_enable = platform_bgmac_clk_enable;
    236	bgmac->cco_ctl_maskset = platform_bgmac_cco_ctl_maskset;
    237	bgmac->get_bus_clock = platform_bgmac_get_bus_clock;
    238	bgmac->cmn_maskset32 = platform_bgmac_cmn_maskset32;
    239	if (of_parse_phandle(np, "phy-handle", 0)) {
    240		bgmac->phy_connect = platform_phy_connect;
    241	} else {
    242		bgmac->phy_connect = bgmac_phy_connect_direct;
    243		bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
    244	}
    245
    246	return bgmac_enet_probe(bgmac);
    247}
    248
    249static int bgmac_remove(struct platform_device *pdev)
    250{
    251	struct bgmac *bgmac = platform_get_drvdata(pdev);
    252
    253	bgmac_enet_remove(bgmac);
    254
    255	return 0;
    256}
    257
    258#ifdef CONFIG_PM
    259static int bgmac_suspend(struct device *dev)
    260{
    261	struct bgmac *bgmac = dev_get_drvdata(dev);
    262
    263	return bgmac_enet_suspend(bgmac);
    264}
    265
    266static int bgmac_resume(struct device *dev)
    267{
    268	struct bgmac *bgmac = dev_get_drvdata(dev);
    269
    270	return bgmac_enet_resume(bgmac);
    271}
    272
    273static const struct dev_pm_ops bgmac_pm_ops = {
    274	.suspend = bgmac_suspend,
    275	.resume = bgmac_resume
    276};
    277
    278#define BGMAC_PM_OPS (&bgmac_pm_ops)
    279#else
    280#define BGMAC_PM_OPS NULL
    281#endif /* CONFIG_PM */
    282
    283static const struct of_device_id bgmac_of_enet_match[] = {
    284	{.compatible = "brcm,amac",},
    285	{.compatible = "brcm,nsp-amac",},
    286	{.compatible = "brcm,ns2-amac",},
    287	{},
    288};
    289
    290MODULE_DEVICE_TABLE(of, bgmac_of_enet_match);
    291
    292static struct platform_driver bgmac_enet_driver = {
    293	.driver = {
    294		.name  = "bgmac-enet",
    295		.of_match_table = bgmac_of_enet_match,
    296		.pm = BGMAC_PM_OPS
    297	},
    298	.probe = bgmac_probe,
    299	.remove = bgmac_remove,
    300};
    301
    302module_platform_driver(bgmac_enet_driver);
    303MODULE_LICENSE("GPL");