1*d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2d70e5326SJon Ringle /** 3d70e5326SJon Ringle * Register map access API - ENCX24J600 support 4d70e5326SJon Ringle * 5d70e5326SJon Ringle * Copyright 2015 Gridpoint 6d70e5326SJon Ringle * 7d70e5326SJon Ringle * Author: Jon Ringle <jringle@gridpoint.com> 8d70e5326SJon Ringle */ 9d70e5326SJon Ringle 10d70e5326SJon Ringle #include <linux/delay.h> 11d70e5326SJon Ringle #include <linux/errno.h> 12d70e5326SJon Ringle #include <linux/init.h> 13d70e5326SJon Ringle #include <linux/module.h> 14d70e5326SJon Ringle #include <linux/netdevice.h> 15d70e5326SJon Ringle #include <linux/regmap.h> 16d70e5326SJon Ringle #include <linux/spi/spi.h> 17d70e5326SJon Ringle 18d70e5326SJon Ringle #include "encx24j600_hw.h" 19d70e5326SJon Ringle 20d70e5326SJon Ringle static inline bool is_bits_set(int value, int mask) 21d70e5326SJon Ringle { 22d70e5326SJon Ringle return (value & mask) == mask; 23d70e5326SJon Ringle } 24d70e5326SJon Ringle 25d70e5326SJon Ringle static int encx24j600_switch_bank(struct encx24j600_context *ctx, 26d70e5326SJon Ringle int bank) 27d70e5326SJon Ringle { 28d70e5326SJon Ringle int ret = 0; 29d70e5326SJon Ringle int bank_opcode = BANK_SELECT(bank); 30b822ee6cSJeroen De Wachter 31d70e5326SJon Ringle ret = spi_write(ctx->spi, &bank_opcode, 1); 32d70e5326SJon Ringle if (ret == 0) 33d70e5326SJon Ringle ctx->bank = bank; 34d70e5326SJon Ringle 35d70e5326SJon Ringle return ret; 36d70e5326SJon Ringle } 37d70e5326SJon Ringle 38d70e5326SJon Ringle static int encx24j600_cmdn(struct encx24j600_context *ctx, u8 opcode, 39d70e5326SJon Ringle const void *buf, size_t len) 40d70e5326SJon Ringle { 41d70e5326SJon Ringle struct spi_message m; 42d70e5326SJon Ringle struct spi_transfer t[2] = { { .tx_buf = &opcode, .len = 1, }, 43d70e5326SJon Ringle { .tx_buf = buf, .len = len }, }; 44d70e5326SJon Ringle spi_message_init(&m); 45d70e5326SJon Ringle spi_message_add_tail(&t[0], &m); 46d70e5326SJon Ringle spi_message_add_tail(&t[1], &m); 47d70e5326SJon Ringle 48d70e5326SJon Ringle return spi_sync(ctx->spi, &m); 49d70e5326SJon Ringle } 50d70e5326SJon Ringle 51d70e5326SJon Ringle static void regmap_lock_mutex(void *context) 52d70e5326SJon Ringle { 53d70e5326SJon Ringle struct encx24j600_context *ctx = context; 54b822ee6cSJeroen De Wachter 55d70e5326SJon Ringle mutex_lock(&ctx->mutex); 56d70e5326SJon Ringle } 57d70e5326SJon Ringle 58d70e5326SJon Ringle static void regmap_unlock_mutex(void *context) 59d70e5326SJon Ringle { 60d70e5326SJon Ringle struct encx24j600_context *ctx = context; 61b822ee6cSJeroen De Wachter 62d70e5326SJon Ringle mutex_unlock(&ctx->mutex); 63d70e5326SJon Ringle } 64d70e5326SJon Ringle 65d70e5326SJon Ringle static int regmap_encx24j600_sfr_read(void *context, u8 reg, u8 *val, 66d70e5326SJon Ringle size_t len) 67d70e5326SJon Ringle { 68d70e5326SJon Ringle struct encx24j600_context *ctx = context; 69d70e5326SJon Ringle u8 banked_reg = reg & ADDR_MASK; 70d70e5326SJon Ringle u8 bank = ((reg & BANK_MASK) >> BANK_SHIFT); 71d70e5326SJon Ringle u8 cmd = RCRU; 72d70e5326SJon Ringle int ret = 0; 73d70e5326SJon Ringle int i = 0; 74d70e5326SJon Ringle u8 tx_buf[2]; 75d70e5326SJon Ringle 76d70e5326SJon Ringle if (reg < 0x80) { 77d70e5326SJon Ringle cmd = RCRCODE | banked_reg; 78d70e5326SJon Ringle if ((banked_reg < 0x16) && (ctx->bank != bank)) 79d70e5326SJon Ringle ret = encx24j600_switch_bank(ctx, bank); 80d70e5326SJon Ringle if (unlikely(ret)) 81d70e5326SJon Ringle return ret; 82d70e5326SJon Ringle } else { 83d70e5326SJon Ringle /* Translate registers that are more effecient using 84d70e5326SJon Ringle * 3-byte SPI commands 85d70e5326SJon Ringle */ 86d70e5326SJon Ringle switch (reg) { 87d70e5326SJon Ringle case EGPRDPT: 88d70e5326SJon Ringle cmd = RGPRDPT; break; 89d70e5326SJon Ringle case EGPWRPT: 90d70e5326SJon Ringle cmd = RGPWRPT; break; 91d70e5326SJon Ringle case ERXRDPT: 92d70e5326SJon Ringle cmd = RRXRDPT; break; 93d70e5326SJon Ringle case ERXWRPT: 94d70e5326SJon Ringle cmd = RRXWRPT; break; 95d70e5326SJon Ringle case EUDARDPT: 96d70e5326SJon Ringle cmd = RUDARDPT; break; 97d70e5326SJon Ringle case EUDAWRPT: 98d70e5326SJon Ringle cmd = RUDAWRPT; break; 99d70e5326SJon Ringle case EGPDATA: 100d70e5326SJon Ringle case ERXDATA: 101d70e5326SJon Ringle case EUDADATA: 102d70e5326SJon Ringle default: 103d70e5326SJon Ringle return -EINVAL; 104d70e5326SJon Ringle } 105d70e5326SJon Ringle } 106d70e5326SJon Ringle 107d70e5326SJon Ringle tx_buf[i++] = cmd; 108d70e5326SJon Ringle if (cmd == RCRU) 109d70e5326SJon Ringle tx_buf[i++] = reg; 110d70e5326SJon Ringle 111d70e5326SJon Ringle ret = spi_write_then_read(ctx->spi, tx_buf, i, val, len); 112d70e5326SJon Ringle 113d70e5326SJon Ringle return ret; 114d70e5326SJon Ringle } 115d70e5326SJon Ringle 116d70e5326SJon Ringle static int regmap_encx24j600_sfr_update(struct encx24j600_context *ctx, 117d70e5326SJon Ringle u8 reg, u8 *val, size_t len, 118d70e5326SJon Ringle u8 unbanked_cmd, u8 banked_code) 119d70e5326SJon Ringle { 120d70e5326SJon Ringle u8 banked_reg = reg & ADDR_MASK; 121d70e5326SJon Ringle u8 bank = ((reg & BANK_MASK) >> BANK_SHIFT); 122d70e5326SJon Ringle u8 cmd = unbanked_cmd; 123d70e5326SJon Ringle struct spi_message m; 124d70e5326SJon Ringle struct spi_transfer t[3] = { { .tx_buf = &cmd, .len = sizeof(cmd), }, 125d70e5326SJon Ringle { .tx_buf = ®, .len = sizeof(reg), }, 126d70e5326SJon Ringle { .tx_buf = val, .len = len }, }; 127d70e5326SJon Ringle 128d70e5326SJon Ringle if (reg < 0x80) { 129d70e5326SJon Ringle int ret = 0; 130b822ee6cSJeroen De Wachter 131d70e5326SJon Ringle cmd = banked_code | banked_reg; 132d70e5326SJon Ringle if ((banked_reg < 0x16) && (ctx->bank != bank)) 133d70e5326SJon Ringle ret = encx24j600_switch_bank(ctx, bank); 134d70e5326SJon Ringle if (unlikely(ret)) 135d70e5326SJon Ringle return ret; 136d70e5326SJon Ringle } else { 137d70e5326SJon Ringle /* Translate registers that are more effecient using 138d70e5326SJon Ringle * 3-byte SPI commands 139d70e5326SJon Ringle */ 140d70e5326SJon Ringle switch (reg) { 141d70e5326SJon Ringle case EGPRDPT: 142d70e5326SJon Ringle cmd = WGPRDPT; break; 143d70e5326SJon Ringle case EGPWRPT: 144d70e5326SJon Ringle cmd = WGPWRPT; break; 145d70e5326SJon Ringle case ERXRDPT: 146d70e5326SJon Ringle cmd = WRXRDPT; break; 147d70e5326SJon Ringle case ERXWRPT: 148d70e5326SJon Ringle cmd = WRXWRPT; break; 149d70e5326SJon Ringle case EUDARDPT: 150d70e5326SJon Ringle cmd = WUDARDPT; break; 151d70e5326SJon Ringle case EUDAWRPT: 152d70e5326SJon Ringle cmd = WUDAWRPT; break; 153d70e5326SJon Ringle case EGPDATA: 154d70e5326SJon Ringle case ERXDATA: 155d70e5326SJon Ringle case EUDADATA: 156d70e5326SJon Ringle default: 157d70e5326SJon Ringle return -EINVAL; 158d70e5326SJon Ringle } 159d70e5326SJon Ringle } 160d70e5326SJon Ringle 161d70e5326SJon Ringle spi_message_init(&m); 162d70e5326SJon Ringle spi_message_add_tail(&t[0], &m); 163d70e5326SJon Ringle 164d70e5326SJon Ringle if (cmd == unbanked_cmd) { 165d70e5326SJon Ringle t[1].tx_buf = ® 166d70e5326SJon Ringle spi_message_add_tail(&t[1], &m); 167d70e5326SJon Ringle } 168d70e5326SJon Ringle 169d70e5326SJon Ringle spi_message_add_tail(&t[2], &m); 170d70e5326SJon Ringle return spi_sync(ctx->spi, &m); 171d70e5326SJon Ringle } 172d70e5326SJon Ringle 173d70e5326SJon Ringle static int regmap_encx24j600_sfr_write(void *context, u8 reg, u8 *val, 174d70e5326SJon Ringle size_t len) 175d70e5326SJon Ringle { 176d70e5326SJon Ringle struct encx24j600_context *ctx = context; 177b822ee6cSJeroen De Wachter 178d70e5326SJon Ringle return regmap_encx24j600_sfr_update(ctx, reg, val, len, WCRU, WCRCODE); 179d70e5326SJon Ringle } 180d70e5326SJon Ringle 181d70e5326SJon Ringle static int regmap_encx24j600_sfr_set_bits(struct encx24j600_context *ctx, 182d70e5326SJon Ringle u8 reg, u8 val) 183d70e5326SJon Ringle { 184d70e5326SJon Ringle return regmap_encx24j600_sfr_update(ctx, reg, &val, 1, BFSU, BFSCODE); 185d70e5326SJon Ringle } 186d70e5326SJon Ringle 187d70e5326SJon Ringle static int regmap_encx24j600_sfr_clr_bits(struct encx24j600_context *ctx, 188d70e5326SJon Ringle u8 reg, u8 val) 189d70e5326SJon Ringle { 190d70e5326SJon Ringle return regmap_encx24j600_sfr_update(ctx, reg, &val, 1, BFCU, BFCCODE); 191d70e5326SJon Ringle } 192d70e5326SJon Ringle 193d70e5326SJon Ringle static int regmap_encx24j600_reg_update_bits(void *context, unsigned int reg, 194d70e5326SJon Ringle unsigned int mask, 195d70e5326SJon Ringle unsigned int val) 196d70e5326SJon Ringle { 197d70e5326SJon Ringle struct encx24j600_context *ctx = context; 198d70e5326SJon Ringle 199d70e5326SJon Ringle int ret = 0; 200d70e5326SJon Ringle unsigned int set_mask = mask & val; 201d70e5326SJon Ringle unsigned int clr_mask = mask & ~val; 202d70e5326SJon Ringle 203d70e5326SJon Ringle if ((reg >= 0x40 && reg < 0x6c) || reg >= 0x80) 204d70e5326SJon Ringle return -EINVAL; 205d70e5326SJon Ringle 206d70e5326SJon Ringle if (set_mask & 0xff) 207d70e5326SJon Ringle ret = regmap_encx24j600_sfr_set_bits(ctx, reg, set_mask); 208d70e5326SJon Ringle 209d70e5326SJon Ringle set_mask = (set_mask & 0xff00) >> 8; 210d70e5326SJon Ringle 211d70e5326SJon Ringle if ((set_mask & 0xff) && (ret == 0)) 212d70e5326SJon Ringle ret = regmap_encx24j600_sfr_set_bits(ctx, reg + 1, set_mask); 213d70e5326SJon Ringle 214d70e5326SJon Ringle if ((clr_mask & 0xff) && (ret == 0)) 215d70e5326SJon Ringle ret = regmap_encx24j600_sfr_clr_bits(ctx, reg, clr_mask); 216d70e5326SJon Ringle 217d70e5326SJon Ringle clr_mask = (clr_mask & 0xff00) >> 8; 218d70e5326SJon Ringle 219d70e5326SJon Ringle if ((clr_mask & 0xff) && (ret == 0)) 220d70e5326SJon Ringle ret = regmap_encx24j600_sfr_clr_bits(ctx, reg + 1, clr_mask); 221d70e5326SJon Ringle 222d70e5326SJon Ringle return ret; 223d70e5326SJon Ringle } 224d70e5326SJon Ringle 225d70e5326SJon Ringle int regmap_encx24j600_spi_write(void *context, u8 reg, const u8 *data, 226d70e5326SJon Ringle size_t count) 227d70e5326SJon Ringle { 228d70e5326SJon Ringle struct encx24j600_context *ctx = context; 229d70e5326SJon Ringle 230d70e5326SJon Ringle if (reg < 0xc0) 231d70e5326SJon Ringle return encx24j600_cmdn(ctx, reg, data, count); 232b822ee6cSJeroen De Wachter 233d70e5326SJon Ringle /* SPI 1-byte command. Ignore data */ 234d70e5326SJon Ringle return spi_write(ctx->spi, ®, 1); 235d70e5326SJon Ringle } 236d70e5326SJon Ringle EXPORT_SYMBOL_GPL(regmap_encx24j600_spi_write); 237d70e5326SJon Ringle 238d70e5326SJon Ringle int regmap_encx24j600_spi_read(void *context, u8 reg, u8 *data, size_t count) 239d70e5326SJon Ringle { 240d70e5326SJon Ringle struct encx24j600_context *ctx = context; 241d70e5326SJon Ringle 242d70e5326SJon Ringle if (reg == RBSEL && count > 1) 243d70e5326SJon Ringle count = 1; 244d70e5326SJon Ringle 245d70e5326SJon Ringle return spi_write_then_read(ctx->spi, ®, sizeof(reg), data, count); 246d70e5326SJon Ringle } 247d70e5326SJon Ringle EXPORT_SYMBOL_GPL(regmap_encx24j600_spi_read); 248d70e5326SJon Ringle 249d70e5326SJon Ringle static int regmap_encx24j600_write(void *context, const void *data, 250d70e5326SJon Ringle size_t len) 251d70e5326SJon Ringle { 252d70e5326SJon Ringle u8 *dout = (u8 *)data; 253d70e5326SJon Ringle u8 reg = dout[0]; 254d70e5326SJon Ringle ++dout; 255d70e5326SJon Ringle --len; 256d70e5326SJon Ringle 257d70e5326SJon Ringle if (reg > 0xa0) 258d70e5326SJon Ringle return regmap_encx24j600_spi_write(context, reg, dout, len); 259d70e5326SJon Ringle 260d70e5326SJon Ringle if (len > 2) 261d70e5326SJon Ringle return -EINVAL; 262d70e5326SJon Ringle 263d70e5326SJon Ringle return regmap_encx24j600_sfr_write(context, reg, dout, len); 264d70e5326SJon Ringle } 265d70e5326SJon Ringle 266d70e5326SJon Ringle static int regmap_encx24j600_read(void *context, 267d70e5326SJon Ringle const void *reg_buf, size_t reg_size, 268d70e5326SJon Ringle void *val, size_t val_size) 269d70e5326SJon Ringle { 270d70e5326SJon Ringle u8 reg = *(const u8 *)reg_buf; 271d70e5326SJon Ringle 272d70e5326SJon Ringle if (reg_size != 1) { 273d70e5326SJon Ringle pr_err("%s: reg=%02x reg_size=%zu\n", __func__, reg, reg_size); 274d70e5326SJon Ringle return -EINVAL; 275d70e5326SJon Ringle } 276d70e5326SJon Ringle 277d70e5326SJon Ringle if (reg > 0xa0) 278d70e5326SJon Ringle return regmap_encx24j600_spi_read(context, reg, val, val_size); 279d70e5326SJon Ringle 280d70e5326SJon Ringle if (val_size > 2) { 281d70e5326SJon Ringle pr_err("%s: reg=%02x val_size=%zu\n", __func__, reg, val_size); 282d70e5326SJon Ringle return -EINVAL; 283d70e5326SJon Ringle } 284d70e5326SJon Ringle 285d70e5326SJon Ringle return regmap_encx24j600_sfr_read(context, reg, val, val_size); 286d70e5326SJon Ringle } 287d70e5326SJon Ringle 288d70e5326SJon Ringle static bool encx24j600_regmap_readable(struct device *dev, unsigned int reg) 289d70e5326SJon Ringle { 290d70e5326SJon Ringle if ((reg < 0x36) || 291d70e5326SJon Ringle ((reg >= 0x40) && (reg < 0x4c)) || 292d70e5326SJon Ringle ((reg >= 0x52) && (reg < 0x56)) || 293d70e5326SJon Ringle ((reg >= 0x60) && (reg < 0x66)) || 294d70e5326SJon Ringle ((reg >= 0x68) && (reg < 0x80)) || 295d70e5326SJon Ringle ((reg >= 0x86) && (reg < 0x92)) || 296d70e5326SJon Ringle (reg == 0xc8)) 297d70e5326SJon Ringle return true; 298d70e5326SJon Ringle else 299d70e5326SJon Ringle return false; 300d70e5326SJon Ringle } 301d70e5326SJon Ringle 302d70e5326SJon Ringle static bool encx24j600_regmap_writeable(struct device *dev, unsigned int reg) 303d70e5326SJon Ringle { 304d70e5326SJon Ringle if ((reg < 0x12) || 305d70e5326SJon Ringle ((reg >= 0x14) && (reg < 0x1a)) || 306d70e5326SJon Ringle ((reg >= 0x1c) && (reg < 0x36)) || 307d70e5326SJon Ringle ((reg >= 0x40) && (reg < 0x4c)) || 308d70e5326SJon Ringle ((reg >= 0x52) && (reg < 0x56)) || 309d70e5326SJon Ringle ((reg >= 0x60) && (reg < 0x68)) || 310d70e5326SJon Ringle ((reg >= 0x6c) && (reg < 0x80)) || 311d70e5326SJon Ringle ((reg >= 0x86) && (reg < 0x92)) || 312d70e5326SJon Ringle ((reg >= 0xc0) && (reg < 0xc8)) || 313d70e5326SJon Ringle ((reg >= 0xca) && (reg < 0xf0))) 314d70e5326SJon Ringle return true; 315d70e5326SJon Ringle else 316d70e5326SJon Ringle return false; 317d70e5326SJon Ringle } 318d70e5326SJon Ringle 319d70e5326SJon Ringle static bool encx24j600_regmap_volatile(struct device *dev, unsigned int reg) 320d70e5326SJon Ringle { 321d70e5326SJon Ringle switch (reg) { 322d70e5326SJon Ringle case ERXHEAD: 323d70e5326SJon Ringle case EDMACS: 324d70e5326SJon Ringle case ETXSTAT: 325d70e5326SJon Ringle case ETXWIRE: 326d70e5326SJon Ringle case ECON1: /* Can be modified via single byte cmds */ 327d70e5326SJon Ringle case ECON2: /* Can be modified via single byte cmds */ 328d70e5326SJon Ringle case ESTAT: 329d70e5326SJon Ringle case EIR: /* Can be modified via single byte cmds */ 330d70e5326SJon Ringle case MIRD: 331d70e5326SJon Ringle case MISTAT: 332d70e5326SJon Ringle return true; 333d70e5326SJon Ringle default: 334d70e5326SJon Ringle break; 335d70e5326SJon Ringle } 336d70e5326SJon Ringle 337d70e5326SJon Ringle return false; 338d70e5326SJon Ringle } 339d70e5326SJon Ringle 340d70e5326SJon Ringle static bool encx24j600_regmap_precious(struct device *dev, unsigned int reg) 341d70e5326SJon Ringle { 342d70e5326SJon Ringle /* single byte cmds are precious */ 343d70e5326SJon Ringle if (((reg >= 0xc0) && (reg < 0xc8)) || 344d70e5326SJon Ringle ((reg >= 0xca) && (reg < 0xf0))) 345d70e5326SJon Ringle return true; 346d70e5326SJon Ringle else 347d70e5326SJon Ringle return false; 348d70e5326SJon Ringle } 349d70e5326SJon Ringle 350d70e5326SJon Ringle static int regmap_encx24j600_phy_reg_read(void *context, unsigned int reg, 351d70e5326SJon Ringle unsigned int *val) 352d70e5326SJon Ringle { 353d70e5326SJon Ringle struct encx24j600_context *ctx = context; 354d70e5326SJon Ringle int ret; 355d70e5326SJon Ringle unsigned int mistat; 356d70e5326SJon Ringle 357d70e5326SJon Ringle reg = MIREGADR_VAL | (reg & PHREG_MASK); 358d70e5326SJon Ringle ret = regmap_write(ctx->regmap, MIREGADR, reg); 359d70e5326SJon Ringle if (unlikely(ret)) 360d70e5326SJon Ringle goto err_out; 361d70e5326SJon Ringle 362d70e5326SJon Ringle ret = regmap_write(ctx->regmap, MICMD, MIIRD); 363d70e5326SJon Ringle if (unlikely(ret)) 364d70e5326SJon Ringle goto err_out; 365d70e5326SJon Ringle 366d70e5326SJon Ringle usleep_range(26, 100); 367d70e5326SJon Ringle while ((ret = regmap_read(ctx->regmap, MISTAT, &mistat) != 0) && 368d70e5326SJon Ringle (mistat & BUSY)) 369d70e5326SJon Ringle cpu_relax(); 370d70e5326SJon Ringle 371d70e5326SJon Ringle if (unlikely(ret)) 372d70e5326SJon Ringle goto err_out; 373d70e5326SJon Ringle 374d70e5326SJon Ringle ret = regmap_write(ctx->regmap, MICMD, 0); 375d70e5326SJon Ringle if (unlikely(ret)) 376d70e5326SJon Ringle goto err_out; 377d70e5326SJon Ringle 378d70e5326SJon Ringle ret = regmap_read(ctx->regmap, MIRD, val); 379d70e5326SJon Ringle 380d70e5326SJon Ringle err_out: 381d70e5326SJon Ringle if (ret) 382d70e5326SJon Ringle pr_err("%s: error %d reading reg %02x\n", __func__, ret, 383d70e5326SJon Ringle reg & PHREG_MASK); 384d70e5326SJon Ringle 385d70e5326SJon Ringle return ret; 386d70e5326SJon Ringle } 387d70e5326SJon Ringle 388d70e5326SJon Ringle static int regmap_encx24j600_phy_reg_write(void *context, unsigned int reg, 389d70e5326SJon Ringle unsigned int val) 390d70e5326SJon Ringle { 391d70e5326SJon Ringle struct encx24j600_context *ctx = context; 392d70e5326SJon Ringle int ret; 393d70e5326SJon Ringle unsigned int mistat; 394d70e5326SJon Ringle 395d70e5326SJon Ringle reg = MIREGADR_VAL | (reg & PHREG_MASK); 396d70e5326SJon Ringle ret = regmap_write(ctx->regmap, MIREGADR, reg); 397d70e5326SJon Ringle if (unlikely(ret)) 398d70e5326SJon Ringle goto err_out; 399d70e5326SJon Ringle 400d70e5326SJon Ringle ret = regmap_write(ctx->regmap, MIWR, val); 401d70e5326SJon Ringle if (unlikely(ret)) 402d70e5326SJon Ringle goto err_out; 403d70e5326SJon Ringle 404d70e5326SJon Ringle usleep_range(26, 100); 405d70e5326SJon Ringle while ((ret = regmap_read(ctx->regmap, MISTAT, &mistat) != 0) && 406d70e5326SJon Ringle (mistat & BUSY)) 407d70e5326SJon Ringle cpu_relax(); 408d70e5326SJon Ringle 409d70e5326SJon Ringle err_out: 410d70e5326SJon Ringle if (ret) 411d70e5326SJon Ringle pr_err("%s: error %d writing reg %02x=%04x\n", __func__, ret, 412d70e5326SJon Ringle reg & PHREG_MASK, val); 413d70e5326SJon Ringle 414d70e5326SJon Ringle return ret; 415d70e5326SJon Ringle } 416d70e5326SJon Ringle 417d70e5326SJon Ringle static bool encx24j600_phymap_readable(struct device *dev, unsigned int reg) 418d70e5326SJon Ringle { 419d70e5326SJon Ringle switch (reg) { 420d70e5326SJon Ringle case PHCON1: 421d70e5326SJon Ringle case PHSTAT1: 422d70e5326SJon Ringle case PHANA: 423d70e5326SJon Ringle case PHANLPA: 424d70e5326SJon Ringle case PHANE: 425d70e5326SJon Ringle case PHCON2: 426d70e5326SJon Ringle case PHSTAT2: 427d70e5326SJon Ringle case PHSTAT3: 428d70e5326SJon Ringle return true; 429d70e5326SJon Ringle default: 430d70e5326SJon Ringle return false; 431d70e5326SJon Ringle } 432d70e5326SJon Ringle } 433d70e5326SJon Ringle 434d70e5326SJon Ringle static bool encx24j600_phymap_writeable(struct device *dev, unsigned int reg) 435d70e5326SJon Ringle { 436d70e5326SJon Ringle switch (reg) { 437d70e5326SJon Ringle case PHCON1: 438d70e5326SJon Ringle case PHCON2: 439d70e5326SJon Ringle case PHANA: 440d70e5326SJon Ringle return true; 441d70e5326SJon Ringle case PHSTAT1: 442d70e5326SJon Ringle case PHSTAT2: 443d70e5326SJon Ringle case PHSTAT3: 444d70e5326SJon Ringle case PHANLPA: 445d70e5326SJon Ringle case PHANE: 446d70e5326SJon Ringle default: 447d70e5326SJon Ringle return false; 448d70e5326SJon Ringle } 449d70e5326SJon Ringle } 450d70e5326SJon Ringle 451d70e5326SJon Ringle static bool encx24j600_phymap_volatile(struct device *dev, unsigned int reg) 452d70e5326SJon Ringle { 453d70e5326SJon Ringle switch (reg) { 454d70e5326SJon Ringle case PHSTAT1: 455d70e5326SJon Ringle case PHSTAT2: 456d70e5326SJon Ringle case PHSTAT3: 457d70e5326SJon Ringle case PHANLPA: 458d70e5326SJon Ringle case PHANE: 459d70e5326SJon Ringle case PHCON2: 460d70e5326SJon Ringle return true; 461d70e5326SJon Ringle default: 462d70e5326SJon Ringle return false; 463d70e5326SJon Ringle } 464d70e5326SJon Ringle } 465d70e5326SJon Ringle 466d70e5326SJon Ringle static struct regmap_config regcfg = { 467d70e5326SJon Ringle .name = "reg", 468d70e5326SJon Ringle .reg_bits = 8, 469d70e5326SJon Ringle .val_bits = 16, 470d70e5326SJon Ringle .max_register = 0xee, 471d70e5326SJon Ringle .reg_stride = 2, 472d70e5326SJon Ringle .cache_type = REGCACHE_RBTREE, 473d70e5326SJon Ringle .val_format_endian = REGMAP_ENDIAN_LITTLE, 474d70e5326SJon Ringle .readable_reg = encx24j600_regmap_readable, 475d70e5326SJon Ringle .writeable_reg = encx24j600_regmap_writeable, 476d70e5326SJon Ringle .volatile_reg = encx24j600_regmap_volatile, 477d70e5326SJon Ringle .precious_reg = encx24j600_regmap_precious, 478d70e5326SJon Ringle .lock = regmap_lock_mutex, 479d70e5326SJon Ringle .unlock = regmap_unlock_mutex, 480d70e5326SJon Ringle }; 481d70e5326SJon Ringle 482d70e5326SJon Ringle static struct regmap_bus regmap_encx24j600 = { 483d70e5326SJon Ringle .write = regmap_encx24j600_write, 484d70e5326SJon Ringle .read = regmap_encx24j600_read, 485d70e5326SJon Ringle .reg_update_bits = regmap_encx24j600_reg_update_bits, 486d70e5326SJon Ringle }; 487d70e5326SJon Ringle 488d70e5326SJon Ringle static struct regmap_config phycfg = { 489d70e5326SJon Ringle .name = "phy", 490d70e5326SJon Ringle .reg_bits = 8, 491d70e5326SJon Ringle .val_bits = 16, 492d70e5326SJon Ringle .max_register = 0x1f, 493d70e5326SJon Ringle .cache_type = REGCACHE_RBTREE, 494d70e5326SJon Ringle .val_format_endian = REGMAP_ENDIAN_LITTLE, 495d70e5326SJon Ringle .readable_reg = encx24j600_phymap_readable, 496d70e5326SJon Ringle .writeable_reg = encx24j600_phymap_writeable, 497d70e5326SJon Ringle .volatile_reg = encx24j600_phymap_volatile, 498d70e5326SJon Ringle }; 499b822ee6cSJeroen De Wachter 500d70e5326SJon Ringle static struct regmap_bus phymap_encx24j600 = { 501d70e5326SJon Ringle .reg_write = regmap_encx24j600_phy_reg_write, 502d70e5326SJon Ringle .reg_read = regmap_encx24j600_phy_reg_read, 503d70e5326SJon Ringle }; 504d70e5326SJon Ringle 505d70e5326SJon Ringle void devm_regmap_init_encx24j600(struct device *dev, 506d70e5326SJon Ringle struct encx24j600_context *ctx) 507d70e5326SJon Ringle { 508d70e5326SJon Ringle mutex_init(&ctx->mutex); 509d70e5326SJon Ringle regcfg.lock_arg = ctx; 510d70e5326SJon Ringle ctx->regmap = devm_regmap_init(dev, ®map_encx24j600, ctx, ®cfg); 511d70e5326SJon Ringle ctx->phymap = devm_regmap_init(dev, &phymap_encx24j600, ctx, &phycfg); 512d70e5326SJon Ringle } 513d70e5326SJon Ringle EXPORT_SYMBOL_GPL(devm_regmap_init_encx24j600); 514d70e5326SJon Ringle 515d70e5326SJon Ringle MODULE_LICENSE("GPL"); 516