Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /* DSA driver for:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Vitesse VSC7385 SparX-G5 5+1-port Integrated Gigabit Ethernet Switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Vitesse VSC7388 SparX-G8 8-port Integrated Gigabit Ethernet Switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Vitesse VSC7395 SparX-G5e 5+1-port Integrated Gigabit Ethernet Switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Vitesse VSC7398 SparX-G8e 8-port Integrated Gigabit Ethernet Switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * This driver takes control of the switch chip connected over CPU-attached
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * address bus and configures it to route packages around when connected to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * a CPU port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * Copyright (C) 2019 Pawel Dembicki <paweldembicki@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * Based on vitesse-vsc-spi.c by:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  * Copyright (C) 2018 Linus Wallej <linus.walleij@linaro.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  * Includes portions of code from the firmware uploader by:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include "vitesse-vsc73xx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define VSC73XX_CMD_PLATFORM_BLOCK_SHIFT		14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define VSC73XX_CMD_PLATFORM_BLOCK_MASK			0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #define VSC73XX_CMD_PLATFORM_SUBBLOCK_SHIFT		10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define VSC73XX_CMD_PLATFORM_SUBBLOCK_MASK		0xf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define VSC73XX_CMD_PLATFORM_REGISTER_SHIFT		2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  * struct vsc73xx_platform - VSC73xx Platform state container
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) struct vsc73xx_platform {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	struct platform_device	*pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	void __iomem		*base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	struct vsc73xx		vsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) static const struct vsc73xx_ops vsc73xx_platform_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) static u32 vsc73xx_make_addr(u8 block, u8 subblock, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	u32 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	ret = (block & VSC73XX_CMD_PLATFORM_BLOCK_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	    << VSC73XX_CMD_PLATFORM_BLOCK_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	ret |= (subblock & VSC73XX_CMD_PLATFORM_SUBBLOCK_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	    << VSC73XX_CMD_PLATFORM_SUBBLOCK_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	ret |= reg << VSC73XX_CMD_PLATFORM_REGISTER_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) static int vsc73xx_platform_read(struct vsc73xx *vsc, u8 block, u8 subblock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 				 u8 reg, u32 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	struct vsc73xx_platform *vsc_platform = vsc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	u32 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	if (!vsc73xx_is_addr_valid(block, subblock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	offset = vsc73xx_make_addr(block, subblock, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	/* By default vsc73xx running in big-endian mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	 * (See "Register Addressing" section 5.5.3 in the VSC7385 manual.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	*val = ioread32be(vsc_platform->base_addr + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) static int vsc73xx_platform_write(struct vsc73xx *vsc, u8 block, u8 subblock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 				  u8 reg, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	struct vsc73xx_platform *vsc_platform = vsc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	u32 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	if (!vsc73xx_is_addr_valid(block, subblock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	offset = vsc73xx_make_addr(block, subblock, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	iowrite32be(val, vsc_platform->base_addr + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) static int vsc73xx_platform_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	struct vsc73xx_platform *vsc_platform;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	vsc_platform = devm_kzalloc(dev, sizeof(*vsc_platform), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	if (!vsc_platform)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	platform_set_drvdata(pdev, vsc_platform);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	vsc_platform->pdev = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	vsc_platform->vsc.dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	vsc_platform->vsc.priv = vsc_platform;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	vsc_platform->vsc.ops = &vsc73xx_platform_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	/* obtain I/O memory space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	vsc_platform->base_addr = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	if (IS_ERR(vsc_platform->base_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		dev_err(&pdev->dev, "cannot request I/O memory space\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		ret = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	return vsc73xx_probe(&vsc_platform->vsc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static int vsc73xx_platform_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	struct vsc73xx_platform *vsc_platform = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	return vsc73xx_remove(&vsc_platform->vsc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static const struct vsc73xx_ops vsc73xx_platform_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	.read = vsc73xx_platform_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	.write = vsc73xx_platform_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static const struct of_device_id vsc73xx_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		.compatible = "vitesse,vsc7385",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		.compatible = "vitesse,vsc7388",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		.compatible = "vitesse,vsc7395",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		.compatible = "vitesse,vsc7398",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	{ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) MODULE_DEVICE_TABLE(of, vsc73xx_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static struct platform_driver vsc73xx_platform_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	.probe = vsc73xx_platform_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	.remove = vsc73xx_platform_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		.name = "vsc73xx-platform",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		.of_match_table = vsc73xx_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) module_platform_driver(vsc73xx_platform_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) MODULE_AUTHOR("Pawel Dembicki <paweldembicki@gmail.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) MODULE_DESCRIPTION("Vitesse VSC7385/7388/7395/7398 Platform driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) MODULE_LICENSE("GPL v2");