Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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	struct device *ddev = &spi->dev;
 38	struct regmap_config rc;
 39	struct ksz_device *dev;
 40	struct ksz8 *ksz8;
 41	int i, ret = 0;
 42
 43	ksz8 = devm_kzalloc(&spi->dev, sizeof(struct ksz8), GFP_KERNEL);
 44	if (!ksz8)
 45		return -ENOMEM;
 46
 47	ksz8->priv = spi;
 48
 49	dev = ksz_switch_alloc(&spi->dev, ksz8);
 50	if (!dev)
 51		return -ENOMEM;
 52
 53	regmap_config = device_get_match_data(ddev);
 54	if (!regmap_config)
 55		return -EINVAL;
 56
 57	for (i = 0; i < ARRAY_SIZE(ksz8795_regmap_config); i++) {
 58		rc = regmap_config[i];
 59		rc.lock_arg = &dev->regmap_mutex;
 60		dev->regmap[i] = devm_regmap_init_spi(spi, &rc);
 61		if (IS_ERR(dev->regmap[i])) {
 62			ret = PTR_ERR(dev->regmap[i]);
 63			dev_err(&spi->dev,
 64				"Failed to initialize regmap%i: %d\n",
 65				regmap_config[i].val_bits, ret);
 66			return ret;
 67		}
 68	}
 69
 70	if (spi->dev.platform_data)
 71		dev->pdata = spi->dev.platform_data;
 72
 73	/* setup spi */
 74	spi->mode = SPI_MODE_3;
 75	ret = spi_setup(spi);
 76	if (ret)
 77		return ret;
 78
 79	ret = ksz8_switch_register(dev);
 80
 81	/* Main DSA driver may not be started yet. */
 82	if (ret)
 83		return ret;
 84
 85	spi_set_drvdata(spi, dev);
 86
 87	return 0;
 88}
 89
 90static int ksz8795_spi_remove(struct spi_device *spi)
 91{
 92	struct ksz_device *dev = spi_get_drvdata(spi);
 93
 94	if (dev)
 95		ksz_switch_remove(dev);
 96
 97	return 0;
 98}
 99
100static void ksz8795_spi_shutdown(struct spi_device *spi)
101{
102	struct ksz_device *dev = spi_get_drvdata(spi);
103
104	if (dev && dev->dev_ops->shutdown)
105		dev->dev_ops->shutdown(dev);
106}
107
108static const struct of_device_id ksz8795_dt_ids[] = {
109	{ .compatible = "microchip,ksz8765", .data = &ksz8795_regmap_config },
110	{ .compatible = "microchip,ksz8794", .data = &ksz8795_regmap_config },
111	{ .compatible = "microchip,ksz8795", .data = &ksz8795_regmap_config },
112	{ .compatible = "microchip,ksz8863", .data = &ksz8863_regmap_config },
113	{ .compatible = "microchip,ksz8873", .data = &ksz8863_regmap_config },
114	{},
115};
116MODULE_DEVICE_TABLE(of, ksz8795_dt_ids);
117
118static struct spi_driver ksz8795_spi_driver = {
119	.driver = {
120		.name	= "ksz8795-switch",
121		.owner	= THIS_MODULE,
122		.of_match_table = of_match_ptr(ksz8795_dt_ids),
123	},
124	.probe	= ksz8795_spi_probe,
125	.remove	= ksz8795_spi_remove,
126	.shutdown = ksz8795_spi_shutdown,
127};
128
129module_spi_driver(ksz8795_spi_driver);
130
131MODULE_AUTHOR("Tristram Ha <Tristram.Ha@microchip.com>");
132MODULE_DESCRIPTION("Microchip KSZ8795 Series Switch SPI Driver");
133MODULE_LICENSE("GPL");