Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v6.19 359 lines 8.1 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) KEBA Industrial Automation Gmbh 2024 4 * 5 * Driver for LAN9252 on KEBA CP500 devices 6 * 7 * This driver is used for updating the configuration of the LAN9252 controller 8 * on KEBA CP500 devices. The LAN9252 is connected over SPI, which is also named 9 * PDI. 10 */ 11 12#include <linux/spi/spi.h> 13#include <linux/mii.h> 14 15/* SPI commands */ 16#define LAN9252_SPI_READ 0x3 17#define LAN9252_SPI_WRITE 0x2 18 19struct lan9252_read_cmd { 20 u8 cmd; 21 u8 addr_0; 22 u8 addr_1; 23} __packed; 24 25struct lan9252_write_cmd { 26 u8 cmd; 27 u8 addr_0; 28 u8 addr_1; 29 u32 data; 30} __packed; 31 32/* byte test register */ 33#define LAN9252_BYTE_TEST 0x64 34#define LAN9252_BYTE_TEST_VALUE 0x87654321 35 36/* hardware configuration register */ 37#define LAN9252_HW_CFG 0x74 38#define LAN9252_HW_CFG_READY 0x08000000 39 40/* EtherCAT CSR interface data register */ 41#define LAN9252_ECAT_CSR_DATA 0x300 42 43/* EtherCAT CSR interface command register */ 44#define LAN9252_ECAT_CSR_CMD 0x304 45#define LAN9252_ECAT_CSR_BUSY 0x80000000 46#define LAN9252_ECAT_CSR_READ 0x40000000 47 48/* EtherCAT slave controller MII register */ 49#define LAN9252_ESC_MII 0x510 50#define LAN9252_ESC_MII_BUSY 0x8000 51#define LAN9252_ESC_MII_CMD_ERR 0x4000 52#define LAN9252_ESC_MII_READ_ERR 0x2000 53#define LAN9252_ESC_MII_ERR_MASK (LAN9252_ESC_MII_CMD_ERR | \ 54 LAN9252_ESC_MII_READ_ERR) 55#define LAN9252_ESC_MII_WRITE 0x0200 56#define LAN9252_ESC_MII_READ 0x0100 57 58/* EtherCAT slave controller PHY address register */ 59#define LAN9252_ESC_PHY_ADDR 0x512 60 61/* EtherCAT slave controller PHY register address register */ 62#define LAN9252_ESC_PHY_REG_ADDR 0x513 63 64/* EtherCAT slave controller PHY data register */ 65#define LAN9252_ESC_PHY_DATA 0x514 66 67/* EtherCAT slave controller PDI access state register */ 68#define LAN9252_ESC_MII_PDI 0x517 69#define LAN9252_ESC_MII_ACCESS_PDI 0x01 70#define LAN9252_ESC_MII_ACCESS_ECAT 0x00 71 72/* PHY address */ 73#define PHY_ADDRESS 2 74 75#define SPI_RETRY_COUNT 10 76#define SPI_WAIT_US 100 77#define SPI_CSR_WAIT_US 500 78 79static int lan9252_spi_read(struct spi_device *spi, u16 addr, u32 *data) 80{ 81 struct lan9252_read_cmd cmd; 82 83 cmd.cmd = LAN9252_SPI_READ; 84 cmd.addr_0 = (addr >> 8) & 0xFF; 85 cmd.addr_1 = addr & 0xFF; 86 87 return spi_write_then_read(spi, (u8 *)&cmd, 88 sizeof(struct lan9252_read_cmd), 89 (u8 *)data, sizeof(u32)); 90} 91 92static int lan9252_spi_write(struct spi_device *spi, u16 addr, u32 data) 93{ 94 struct lan9252_write_cmd cmd; 95 96 cmd.cmd = LAN9252_SPI_WRITE; 97 cmd.addr_0 = (addr >> 8) & 0xFF; 98 cmd.addr_1 = addr & 0xFF; 99 cmd.data = data; 100 101 return spi_write(spi, (u8 *)&cmd, sizeof(struct lan9252_write_cmd)); 102} 103 104static bool lan9252_init(struct spi_device *spi) 105{ 106 u32 data; 107 int ret; 108 109 ret = lan9252_spi_read(spi, LAN9252_BYTE_TEST, &data); 110 if (ret || data != LAN9252_BYTE_TEST_VALUE) 111 return false; 112 113 ret = lan9252_spi_read(spi, LAN9252_HW_CFG, &data); 114 if (ret || !(data & LAN9252_HW_CFG_READY)) 115 return false; 116 117 return true; 118} 119 120static u8 lan9252_esc_get_size(u16 addr) 121{ 122 if (addr == LAN9252_ESC_MII || addr == LAN9252_ESC_PHY_DATA) 123 return 2; 124 125 return 1; 126} 127 128static int lan9252_esc_wait(struct spi_device *spi) 129{ 130 ktime_t timeout = ktime_add_us(ktime_get(), SPI_WAIT_US); 131 u32 data; 132 int ret; 133 134 /* wait while CSR command is busy */ 135 for (;;) { 136 ret = lan9252_spi_read(spi, LAN9252_ECAT_CSR_CMD, &data); 137 if (ret) 138 return ret; 139 if (!(data & LAN9252_ECAT_CSR_BUSY)) 140 return 0; 141 142 if (ktime_compare(ktime_get(), timeout) > 0) { 143 ret = lan9252_spi_read(spi, LAN9252_ECAT_CSR_CMD, &data); 144 if (ret) 145 return ret; 146 break; 147 } 148 } 149 150 return (!(data & LAN9252_ECAT_CSR_BUSY)) ? 0 : -ETIMEDOUT; 151} 152 153static int lan9252_esc_read(struct spi_device *spi, u16 addr, u32 *data) 154{ 155 u32 csr_cmd; 156 u8 size; 157 int ret; 158 159 size = lan9252_esc_get_size(addr); 160 csr_cmd = LAN9252_ECAT_CSR_BUSY | LAN9252_ECAT_CSR_READ; 161 csr_cmd |= (size << 16) | addr; 162 ret = lan9252_spi_write(spi, LAN9252_ECAT_CSR_CMD, csr_cmd); 163 if (ret) 164 return ret; 165 166 ret = lan9252_esc_wait(spi); 167 if (ret) 168 return ret; 169 170 ret = lan9252_spi_read(spi, LAN9252_ECAT_CSR_DATA, data); 171 if (ret) 172 return ret; 173 174 return 0; 175} 176 177static int lan9252_esc_write(struct spi_device *spi, u16 addr, u32 data) 178{ 179 u32 csr_cmd; 180 u8 size; 181 int ret; 182 183 ret = lan9252_spi_write(spi, LAN9252_ECAT_CSR_DATA, data); 184 if (ret) 185 return ret; 186 187 size = lan9252_esc_get_size(addr); 188 csr_cmd = LAN9252_ECAT_CSR_BUSY; 189 csr_cmd |= (size << 16) | addr; 190 ret = lan9252_spi_write(spi, LAN9252_ECAT_CSR_CMD, csr_cmd); 191 if (ret) 192 return ret; 193 194 ret = lan9252_esc_wait(spi); 195 if (ret) 196 return ret; 197 198 return 0; 199} 200 201static int lan9252_access_mii(struct spi_device *spi, bool access) 202{ 203 u32 data; 204 205 if (access) 206 data = LAN9252_ESC_MII_ACCESS_PDI; 207 else 208 data = LAN9252_ESC_MII_ACCESS_ECAT; 209 210 return lan9252_esc_write(spi, LAN9252_ESC_MII_PDI, data); 211} 212 213static int lan9252_mii_wait(struct spi_device *spi) 214{ 215 ktime_t timeout = ktime_add_us(ktime_get(), SPI_CSR_WAIT_US); 216 u32 data; 217 int ret; 218 219 /* wait while MII control state machine is busy */ 220 for (;;) { 221 ret = lan9252_esc_read(spi, LAN9252_ESC_MII, &data); 222 if (ret) 223 return ret; 224 if (data & LAN9252_ESC_MII_ERR_MASK) 225 return -EIO; 226 if (!(data & LAN9252_ESC_MII_BUSY)) 227 return 0; 228 229 if (ktime_compare(ktime_get(), timeout) > 0) { 230 ret = lan9252_esc_read(spi, LAN9252_ESC_MII, &data); 231 if (ret) 232 return ret; 233 if (data & LAN9252_ESC_MII_ERR_MASK) 234 return -EIO; 235 break; 236 } 237 } 238 239 return (!(data & LAN9252_ESC_MII_BUSY)) ? 0 : -ETIMEDOUT; 240} 241 242static int lan9252_mii_read(struct spi_device *spi, u8 phy_addr, u8 reg_addr, 243 u32 *data) 244{ 245 int ret; 246 247 ret = lan9252_esc_write(spi, LAN9252_ESC_PHY_ADDR, phy_addr); 248 if (ret) 249 return ret; 250 ret = lan9252_esc_write(spi, LAN9252_ESC_PHY_REG_ADDR, reg_addr); 251 if (ret) 252 return ret; 253 254 ret = lan9252_esc_write(spi, LAN9252_ESC_MII, LAN9252_ESC_MII_READ); 255 if (ret) 256 return ret; 257 258 ret = lan9252_mii_wait(spi); 259 if (ret) 260 return ret; 261 262 return lan9252_esc_read(spi, LAN9252_ESC_PHY_DATA, data); 263} 264 265static int lan9252_mii_write(struct spi_device *spi, u8 phy_addr, u8 reg_addr, 266 u32 data) 267{ 268 int ret; 269 270 ret = lan9252_esc_write(spi, LAN9252_ESC_PHY_ADDR, phy_addr); 271 if (ret) 272 return ret; 273 ret = lan9252_esc_write(spi, LAN9252_ESC_PHY_REG_ADDR, reg_addr); 274 if (ret) 275 return ret; 276 ret = lan9252_esc_write(spi, LAN9252_ESC_PHY_DATA, data); 277 if (ret) 278 return ret; 279 280 ret = lan9252_esc_write(spi, LAN9252_ESC_MII, LAN9252_ESC_MII_WRITE); 281 if (ret) 282 return ret; 283 284 return lan9252_mii_wait(spi); 285} 286 287static int lan9252_probe(struct spi_device *spi) 288{ 289 u32 data; 290 int retry = SPI_RETRY_COUNT; 291 int ret; 292 293 /* execute specified initialization sequence */ 294 while (retry && !lan9252_init(spi)) 295 retry--; 296 if (retry == 0) { 297 dev_err(&spi->dev, 298 "Can't initialize LAN9252 SPI communication!"); 299 return -EIO; 300 } 301 302 /* enable access to MII management for PDI */ 303 ret = lan9252_access_mii(spi, true); 304 if (ret) { 305 dev_err(&spi->dev, "Can't enable access to MII management!"); 306 return ret; 307 } 308 309 /* 310 * check PHY configuration and configure if necessary 311 * - full duplex 312 * - auto negotiation disabled 313 * - 100 Mbps 314 */ 315 ret = lan9252_mii_read(spi, PHY_ADDRESS, MII_BMCR, &data); 316 if (ret) { 317 dev_err(&spi->dev, "Can't read LAN9252 configuration!"); 318 goto out; 319 } 320 if (!(data & BMCR_FULLDPLX) || (data & BMCR_ANENABLE) || 321 !(data & BMCR_SPEED100)) { 322 /* 323 */ 324 data &= ~(BMCR_ANENABLE); 325 data |= (BMCR_FULLDPLX | BMCR_SPEED100); 326 ret = lan9252_mii_write(spi, PHY_ADDRESS, MII_BMCR, data); 327 if (ret) 328 dev_err(&spi->dev, 329 "Can't write LAN9252 configuration!"); 330 } 331 332 dev_info(&spi->dev, "LAN9252 PHY configuration"); 333 334out: 335 /* disable access to MII management for PDI */ 336 lan9252_access_mii(spi, false); 337 338 return ret; 339} 340 341static const struct spi_device_id lan9252_id[] = { 342 {"lan9252"}, 343 {} 344}; 345MODULE_DEVICE_TABLE(spi, lan9252_id); 346 347static struct spi_driver lan9252_driver = { 348 .driver = { 349 .name = "lan9252", 350 }, 351 .probe = lan9252_probe, 352 .id_table = lan9252_id, 353}; 354module_spi_driver(lan9252_driver); 355 356MODULE_AUTHOR("Petar Bojanic <boja@keba.com>"); 357MODULE_AUTHOR("Gerhard Engleder <eg@keba.com>"); 358MODULE_DESCRIPTION("KEBA LAN9252 driver"); 359MODULE_LICENSE("GPL");