1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Microchip ksz 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 28 #define KSZ9477_SPI_ADDR_SHIFT 24 29 #define KSZ9477_SPI_ADDR_ALIGN 3 30 #define KSZ9477_SPI_TURNAROUND_SHIFT 5 31 32 KSZ_REGMAP_TABLE(ksz8795, 16, KSZ8795_SPI_ADDR_SHIFT, 33 KSZ8795_SPI_TURNAROUND_SHIFT, KSZ8795_SPI_ADDR_ALIGN); 34 35 KSZ_REGMAP_TABLE(ksz8863, 16, KSZ8863_SPI_ADDR_SHIFT, 36 KSZ8863_SPI_TURNAROUND_SHIFT, KSZ8863_SPI_ADDR_ALIGN); 37 38 KSZ_REGMAP_TABLE(ksz9477, 32, KSZ9477_SPI_ADDR_SHIFT, 39 KSZ9477_SPI_TURNAROUND_SHIFT, KSZ9477_SPI_ADDR_ALIGN); 40 41 static int ksz_spi_probe(struct spi_device *spi) 42 { 43 const struct regmap_config *regmap_config; 44 const struct ksz_chip_data *chip; 45 struct device *ddev = &spi->dev; 46 struct regmap_config rc; 47 struct ksz_device *dev; 48 struct ksz8 *ksz8; 49 int i, ret = 0; 50 51 ksz8 = devm_kzalloc(&spi->dev, sizeof(struct ksz8), GFP_KERNEL); 52 if (!ksz8) 53 return -ENOMEM; 54 55 ksz8->priv = spi; 56 57 dev = ksz_switch_alloc(&spi->dev, ksz8); 58 if (!dev) 59 return -ENOMEM; 60 61 chip = device_get_match_data(ddev); 62 if (!chip) 63 return -EINVAL; 64 65 if (chip->chip_id == KSZ8830_CHIP_ID) 66 regmap_config = ksz8863_regmap_config; 67 else if (chip->chip_id == KSZ8795_CHIP_ID || 68 chip->chip_id == KSZ8794_CHIP_ID || 69 chip->chip_id == KSZ8765_CHIP_ID) 70 regmap_config = ksz8795_regmap_config; 71 else 72 regmap_config = ksz9477_regmap_config; 73 74 for (i = 0; i < ARRAY_SIZE(ksz8795_regmap_config); i++) { 75 rc = regmap_config[i]; 76 rc.lock_arg = &dev->regmap_mutex; 77 dev->regmap[i] = devm_regmap_init_spi(spi, &rc); 78 if (IS_ERR(dev->regmap[i])) { 79 ret = PTR_ERR(dev->regmap[i]); 80 dev_err(&spi->dev, 81 "Failed to initialize regmap%i: %d\n", 82 regmap_config[i].val_bits, ret); 83 return ret; 84 } 85 } 86 87 if (spi->dev.platform_data) 88 dev->pdata = spi->dev.platform_data; 89 90 /* setup spi */ 91 spi->mode = SPI_MODE_3; 92 ret = spi_setup(spi); 93 if (ret) 94 return ret; 95 96 ret = ksz_switch_register(dev); 97 98 /* Main DSA driver may not be started yet. */ 99 if (ret) 100 return ret; 101 102 spi_set_drvdata(spi, dev); 103 104 return 0; 105 } 106 107 static void ksz_spi_remove(struct spi_device *spi) 108 { 109 struct ksz_device *dev = spi_get_drvdata(spi); 110 111 if (dev) 112 ksz_switch_remove(dev); 113 114 spi_set_drvdata(spi, NULL); 115 } 116 117 static void ksz_spi_shutdown(struct spi_device *spi) 118 { 119 struct ksz_device *dev = spi_get_drvdata(spi); 120 121 if (!dev) 122 return; 123 124 if (dev->dev_ops->reset) 125 dev->dev_ops->reset(dev); 126 127 dsa_switch_shutdown(dev->ds); 128 129 spi_set_drvdata(spi, NULL); 130 } 131 132 static const struct of_device_id ksz_dt_ids[] = { 133 { 134 .compatible = "microchip,ksz8765", 135 .data = &ksz_switch_chips[KSZ8765] 136 }, 137 { 138 .compatible = "microchip,ksz8794", 139 .data = &ksz_switch_chips[KSZ8794] 140 }, 141 { 142 .compatible = "microchip,ksz8795", 143 .data = &ksz_switch_chips[KSZ8795] 144 }, 145 { 146 .compatible = "microchip,ksz8863", 147 .data = &ksz_switch_chips[KSZ8830] 148 }, 149 { 150 .compatible = "microchip,ksz8873", 151 .data = &ksz_switch_chips[KSZ8830] 152 }, 153 { 154 .compatible = "microchip,ksz9477", 155 .data = &ksz_switch_chips[KSZ9477] 156 }, 157 { 158 .compatible = "microchip,ksz9897", 159 .data = &ksz_switch_chips[KSZ9897] 160 }, 161 { 162 .compatible = "microchip,ksz9893", 163 .data = &ksz_switch_chips[KSZ9893] 164 }, 165 { 166 .compatible = "microchip,ksz9563", 167 .data = &ksz_switch_chips[KSZ9893] 168 }, 169 { 170 .compatible = "microchip,ksz8563", 171 .data = &ksz_switch_chips[KSZ9893] 172 }, 173 { 174 .compatible = "microchip,ksz9567", 175 .data = &ksz_switch_chips[KSZ9567] 176 }, 177 {}, 178 }; 179 MODULE_DEVICE_TABLE(of, ksz_dt_ids); 180 181 static const struct spi_device_id ksz_spi_ids[] = { 182 { "ksz8765" }, 183 { "ksz8794" }, 184 { "ksz8795" }, 185 { "ksz8863" }, 186 { "ksz8873" }, 187 { "ksz9477" }, 188 { "ksz9897" }, 189 { "ksz9893" }, 190 { "ksz9563" }, 191 { "ksz8563" }, 192 { "ksz9567" }, 193 { }, 194 }; 195 MODULE_DEVICE_TABLE(spi, ksz_spi_ids); 196 197 static struct spi_driver ksz_spi_driver = { 198 .driver = { 199 .name = "ksz-switch", 200 .owner = THIS_MODULE, 201 .of_match_table = of_match_ptr(ksz_dt_ids), 202 }, 203 .id_table = ksz_spi_ids, 204 .probe = ksz_spi_probe, 205 .remove = ksz_spi_remove, 206 .shutdown = ksz_spi_shutdown, 207 }; 208 209 module_spi_driver(ksz_spi_driver); 210 211 MODULE_ALIAS("spi:ksz9477"); 212 MODULE_ALIAS("spi:ksz9897"); 213 MODULE_ALIAS("spi:ksz9893"); 214 MODULE_ALIAS("spi:ksz9563"); 215 MODULE_ALIAS("spi:ksz8563"); 216 MODULE_ALIAS("spi:ksz9567"); 217 MODULE_AUTHOR("Tristram Ha <Tristram.Ha@microchip.com>"); 218 MODULE_DESCRIPTION("Microchip ksz Series Switch SPI Driver"); 219 MODULE_LICENSE("GPL"); 220