252 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Microchip ksz series register access through SPI4 *5 * Copyright (C) 2017-2024 Microchip Technology Inc.6 * Tristram Ha <Tristram.Ha@microchip.com>7 */8 9#include <linux/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 "ksz_common.h"18 19#define KSZ8795_SPI_ADDR_SHIFT 1220#define KSZ8795_SPI_ADDR_ALIGN 321#define KSZ8795_SPI_TURNAROUND_SHIFT 122 23#define KSZ8863_SPI_ADDR_SHIFT 824#define KSZ8863_SPI_ADDR_ALIGN 825#define KSZ8863_SPI_TURNAROUND_SHIFT 026 27#define KSZ9477_SPI_ADDR_SHIFT 2428#define KSZ9477_SPI_ADDR_ALIGN 329#define KSZ9477_SPI_TURNAROUND_SHIFT 530 31KSZ_REGMAP_TABLE(ksz8795, 16, KSZ8795_SPI_ADDR_SHIFT,32 KSZ8795_SPI_TURNAROUND_SHIFT, KSZ8795_SPI_ADDR_ALIGN);33 34KSZ_REGMAP_TABLE(ksz8863, 16, KSZ8863_SPI_ADDR_SHIFT,35 KSZ8863_SPI_TURNAROUND_SHIFT, KSZ8863_SPI_ADDR_ALIGN);36 37KSZ_REGMAP_TABLE(ksz9477, 32, KSZ9477_SPI_ADDR_SHIFT,38 KSZ9477_SPI_TURNAROUND_SHIFT, KSZ9477_SPI_ADDR_ALIGN);39 40static int ksz_spi_probe(struct spi_device *spi)41{42 const struct regmap_config *regmap_config;43 const struct ksz_chip_data *chip;44 struct device *ddev = &spi->dev;45 struct regmap_config rc;46 struct ksz_device *dev;47 int i, ret = 0;48 49 dev = ksz_switch_alloc(&spi->dev, spi);50 if (!dev)51 return -ENOMEM;52 53 chip = device_get_match_data(ddev);54 if (!chip)55 return -EINVAL;56 57 if (chip->chip_id == KSZ88X3_CHIP_ID)58 regmap_config = ksz8863_regmap_config;59 else if (chip->chip_id == KSZ8795_CHIP_ID ||60 chip->chip_id == KSZ8794_CHIP_ID ||61 chip->chip_id == KSZ8765_CHIP_ID)62 regmap_config = ksz8795_regmap_config;63 else if (chip->chip_id == KSZ8895_CHIP_ID ||64 chip->chip_id == KSZ8864_CHIP_ID)65 regmap_config = ksz8863_regmap_config;66 else67 regmap_config = ksz9477_regmap_config;68 69 for (i = 0; i < __KSZ_NUM_REGMAPS; i++) {70 rc = regmap_config[i];71 rc.lock_arg = &dev->regmap_mutex;72 rc.wr_table = chip->wr_table;73 rc.rd_table = chip->rd_table;74 dev->regmap[i] = devm_regmap_init_spi(spi, &rc);75 76 if (IS_ERR(dev->regmap[i])) {77 return dev_err_probe(&spi->dev, PTR_ERR(dev->regmap[i]),78 "Failed to initialize regmap%i\n",79 regmap_config[i].val_bits);80 }81 }82 83 if (spi->dev.platform_data)84 dev->pdata = spi->dev.platform_data;85 86 /* setup spi */87 spi->mode = SPI_MODE_3;88 ret = spi_setup(spi);89 if (ret)90 return ret;91 92 dev->irq = spi->irq;93 94 ret = ksz_switch_register(dev);95 96 /* Main DSA driver may not be started yet. */97 if (ret)98 return ret;99 100 spi_set_drvdata(spi, dev);101 102 return 0;103}104 105static void ksz_spi_remove(struct spi_device *spi)106{107 struct ksz_device *dev = spi_get_drvdata(spi);108 109 if (dev)110 ksz_switch_remove(dev);111}112 113static void ksz_spi_shutdown(struct spi_device *spi)114{115 struct ksz_device *dev = spi_get_drvdata(spi);116 117 if (!dev)118 return;119 120 ksz_switch_shutdown(dev);121 122 spi_set_drvdata(spi, NULL);123}124 125static const struct of_device_id ksz_dt_ids[] = {126 {127 .compatible = "microchip,ksz8765",128 .data = &ksz_switch_chips[KSZ8765]129 },130 {131 .compatible = "microchip,ksz8794",132 .data = &ksz_switch_chips[KSZ8794]133 },134 {135 .compatible = "microchip,ksz8795",136 .data = &ksz_switch_chips[KSZ8795]137 },138 {139 .compatible = "microchip,ksz8863",140 .data = &ksz_switch_chips[KSZ88X3]141 },142 {143 .compatible = "microchip,ksz8864",144 .data = &ksz_switch_chips[KSZ8864]145 },146 {147 .compatible = "microchip,ksz8873",148 .data = &ksz_switch_chips[KSZ88X3]149 },150 {151 .compatible = "microchip,ksz8895",152 .data = &ksz_switch_chips[KSZ8895]153 },154 {155 .compatible = "microchip,ksz9477",156 .data = &ksz_switch_chips[KSZ9477]157 },158 {159 .compatible = "microchip,ksz9896",160 .data = &ksz_switch_chips[KSZ9896]161 },162 {163 .compatible = "microchip,ksz9897",164 .data = &ksz_switch_chips[KSZ9897]165 },166 {167 .compatible = "microchip,ksz9893",168 .data = &ksz_switch_chips[KSZ9893]169 },170 {171 .compatible = "microchip,ksz9563",172 .data = &ksz_switch_chips[KSZ9563]173 },174 {175 .compatible = "microchip,ksz8563",176 .data = &ksz_switch_chips[KSZ8563]177 },178 {179 .compatible = "microchip,ksz8567",180 .data = &ksz_switch_chips[KSZ8567]181 },182 {183 .compatible = "microchip,ksz9567",184 .data = &ksz_switch_chips[KSZ9567]185 },186 {187 .compatible = "microchip,lan9370",188 .data = &ksz_switch_chips[LAN9370]189 },190 {191 .compatible = "microchip,lan9371",192 .data = &ksz_switch_chips[LAN9371]193 },194 {195 .compatible = "microchip,lan9372",196 .data = &ksz_switch_chips[LAN9372]197 },198 {199 .compatible = "microchip,lan9373",200 .data = &ksz_switch_chips[LAN9373]201 },202 {203 .compatible = "microchip,lan9374",204 .data = &ksz_switch_chips[LAN9374]205 },206 {},207};208MODULE_DEVICE_TABLE(of, ksz_dt_ids);209 210static const struct spi_device_id ksz_spi_ids[] = {211 { "ksz8765" },212 { "ksz8794" },213 { "ksz8795" },214 { "ksz8863" },215 { "ksz8864" },216 { "ksz8873" },217 { "ksz8895" },218 { "ksz9477" },219 { "ksz9896" },220 { "ksz9897" },221 { "ksz9893" },222 { "ksz9563" },223 { "ksz8563" },224 { "ksz8567" },225 { "ksz9567" },226 { "lan9370" },227 { "lan9371" },228 { "lan9372" },229 { "lan9373" },230 { "lan9374" },231 { },232};233MODULE_DEVICE_TABLE(spi, ksz_spi_ids);234 235static struct spi_driver ksz_spi_driver = {236 .driver = {237 .name = "ksz-switch",238 .of_match_table = ksz_dt_ids,239 },240 .id_table = ksz_spi_ids,241 .probe = ksz_spi_probe,242 .remove = ksz_spi_remove,243 .shutdown = ksz_spi_shutdown,244};245 246module_spi_driver(ksz_spi_driver);247 248MODULE_ALIAS("spi:lan937x");249MODULE_AUTHOR("Tristram Ha <Tristram.Ha@microchip.com>");250MODULE_DESCRIPTION("Microchip ksz Series Switch SPI Driver");251MODULE_LICENSE("GPL");252