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

ksz8795_spi.c (3778B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Microchip KSZ8795 series register access through SPI
      4 *
      5 * Copyright (C) 2017 Microchip Technology Inc.
      6 *	Tristram Ha <Tristram.Ha@microchip.com>
      7 */
      8
      9#include <asm/unaligned.h>
     10
     11#include <linux/delay.h>
     12#include <linux/kernel.h>
     13#include <linux/module.h>
     14#include <linux/regmap.h>
     15#include <linux/spi/spi.h>
     16
     17#include "ksz8.h"
     18#include "ksz_common.h"
     19
     20#define KSZ8795_SPI_ADDR_SHIFT			12
     21#define KSZ8795_SPI_ADDR_ALIGN			3
     22#define KSZ8795_SPI_TURNAROUND_SHIFT		1
     23
     24#define KSZ8863_SPI_ADDR_SHIFT			8
     25#define KSZ8863_SPI_ADDR_ALIGN			8
     26#define KSZ8863_SPI_TURNAROUND_SHIFT		0
     27
     28KSZ_REGMAP_TABLE(ksz8795, 16, KSZ8795_SPI_ADDR_SHIFT,
     29		 KSZ8795_SPI_TURNAROUND_SHIFT, KSZ8795_SPI_ADDR_ALIGN);
     30
     31KSZ_REGMAP_TABLE(ksz8863, 16, KSZ8863_SPI_ADDR_SHIFT,
     32		 KSZ8863_SPI_TURNAROUND_SHIFT, KSZ8863_SPI_ADDR_ALIGN);
     33
     34static int ksz8795_spi_probe(struct spi_device *spi)
     35{
     36	const struct regmap_config *regmap_config;
     37	const struct ksz_chip_data *chip;
     38	struct device *ddev = &spi->dev;
     39	struct regmap_config rc;
     40	struct ksz_device *dev;
     41	struct ksz8 *ksz8;
     42	int i, ret = 0;
     43
     44	ksz8 = devm_kzalloc(&spi->dev, sizeof(struct ksz8), GFP_KERNEL);
     45	if (!ksz8)
     46		return -ENOMEM;
     47
     48	ksz8->priv = spi;
     49
     50	dev = ksz_switch_alloc(&spi->dev, ksz8);
     51	if (!dev)
     52		return -ENOMEM;
     53
     54	chip = device_get_match_data(ddev);
     55	if (!chip)
     56		return -EINVAL;
     57
     58	if (chip->chip_id == KSZ8830_CHIP_ID)
     59		regmap_config = ksz8863_regmap_config;
     60	else
     61		regmap_config = ksz8795_regmap_config;
     62
     63	for (i = 0; i < ARRAY_SIZE(ksz8795_regmap_config); i++) {
     64		rc = regmap_config[i];
     65		rc.lock_arg = &dev->regmap_mutex;
     66		dev->regmap[i] = devm_regmap_init_spi(spi, &rc);
     67		if (IS_ERR(dev->regmap[i])) {
     68			ret = PTR_ERR(dev->regmap[i]);
     69			dev_err(&spi->dev,
     70				"Failed to initialize regmap%i: %d\n",
     71				regmap_config[i].val_bits, ret);
     72			return ret;
     73		}
     74	}
     75
     76	if (spi->dev.platform_data)
     77		dev->pdata = spi->dev.platform_data;
     78
     79	/* setup spi */
     80	spi->mode = SPI_MODE_3;
     81	ret = spi_setup(spi);
     82	if (ret)
     83		return ret;
     84
     85	ret = ksz8_switch_register(dev);
     86
     87	/* Main DSA driver may not be started yet. */
     88	if (ret)
     89		return ret;
     90
     91	spi_set_drvdata(spi, dev);
     92
     93	return 0;
     94}
     95
     96static void ksz8795_spi_remove(struct spi_device *spi)
     97{
     98	struct ksz_device *dev = spi_get_drvdata(spi);
     99
    100	if (dev)
    101		ksz_switch_remove(dev);
    102
    103	spi_set_drvdata(spi, NULL);
    104}
    105
    106static void ksz8795_spi_shutdown(struct spi_device *spi)
    107{
    108	struct ksz_device *dev = spi_get_drvdata(spi);
    109
    110	if (!dev)
    111		return;
    112
    113	if (dev->dev_ops->shutdown)
    114		dev->dev_ops->shutdown(dev);
    115
    116	dsa_switch_shutdown(dev->ds);
    117
    118	spi_set_drvdata(spi, NULL);
    119}
    120
    121static const struct of_device_id ksz8795_dt_ids[] = {
    122	{
    123		.compatible = "microchip,ksz8765",
    124		.data = &ksz_switch_chips[KSZ8765]
    125	},
    126	{
    127		.compatible = "microchip,ksz8794",
    128		.data = &ksz_switch_chips[KSZ8794]
    129	},
    130	{
    131		.compatible = "microchip,ksz8795",
    132		.data = &ksz_switch_chips[KSZ8795]
    133	},
    134	{
    135		.compatible = "microchip,ksz8863",
    136		.data = &ksz_switch_chips[KSZ8830]
    137	},
    138	{
    139		.compatible = "microchip,ksz8873",
    140		.data = &ksz_switch_chips[KSZ8830]
    141	},
    142	{},
    143};
    144MODULE_DEVICE_TABLE(of, ksz8795_dt_ids);
    145
    146static const struct spi_device_id ksz8795_spi_ids[] = {
    147	{ "ksz8765" },
    148	{ "ksz8794" },
    149	{ "ksz8795" },
    150	{ "ksz8863" },
    151	{ "ksz8873" },
    152	{ },
    153};
    154MODULE_DEVICE_TABLE(spi, ksz8795_spi_ids);
    155
    156static struct spi_driver ksz8795_spi_driver = {
    157	.driver = {
    158		.name	= "ksz8795-switch",
    159		.owner	= THIS_MODULE,
    160		.of_match_table = of_match_ptr(ksz8795_dt_ids),
    161	},
    162	.id_table = ksz8795_spi_ids,
    163	.probe	= ksz8795_spi_probe,
    164	.remove	= ksz8795_spi_remove,
    165	.shutdown = ksz8795_spi_shutdown,
    166};
    167
    168module_spi_driver(ksz8795_spi_driver);
    169
    170MODULE_AUTHOR("Tristram Ha <Tristram.Ha@microchip.com>");
    171MODULE_DESCRIPTION("Microchip KSZ8795 Series Switch SPI Driver");
    172MODULE_LICENSE("GPL");