root/drivers/net/dsa/b53/b53_spi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. b53_spi_read_reg
  2. b53_spi_clear_status
  3. b53_spi_set_page
  4. b53_prepare_reg_access
  5. b53_spi_prepare_reg_read
  6. b53_spi_read
  7. b53_spi_read8
  8. b53_spi_read16
  9. b53_spi_read32
  10. b53_spi_read48
  11. b53_spi_read64
  12. b53_spi_write8
  13. b53_spi_write16
  14. b53_spi_write32
  15. b53_spi_write48
  16. b53_spi_write64
  17. b53_spi_probe
  18. b53_spi_remove

   1 /*
   2  * B53 register access through SPI
   3  *
   4  * Copyright (C) 2011-2013 Jonas Gorski <jogo@openwrt.org>
   5  *
   6  * Permission to use, copy, modify, and/or distribute this software for any
   7  * purpose with or without fee is hereby granted, provided that the above
   8  * copyright notice and this permission notice appear in all copies.
   9  *
  10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17  */
  18 
  19 #include <asm/unaligned.h>
  20 
  21 #include <linux/delay.h>
  22 #include <linux/kernel.h>
  23 #include <linux/module.h>
  24 #include <linux/spi/spi.h>
  25 #include <linux/platform_data/b53.h>
  26 
  27 #include "b53_priv.h"
  28 
  29 #define B53_SPI_DATA            0xf0
  30 
  31 #define B53_SPI_STATUS          0xfe
  32 #define B53_SPI_CMD_SPIF        BIT(7)
  33 #define B53_SPI_CMD_RACK        BIT(5)
  34 
  35 #define B53_SPI_CMD_READ        0x00
  36 #define B53_SPI_CMD_WRITE       0x01
  37 #define B53_SPI_CMD_NORMAL      0x60
  38 #define B53_SPI_CMD_FAST        0x10
  39 
  40 #define B53_SPI_PAGE_SELECT     0xff
  41 
  42 static inline int b53_spi_read_reg(struct spi_device *spi, u8 reg, u8 *val,
  43                                    unsigned int len)
  44 {
  45         u8 txbuf[2];
  46 
  47         txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_READ;
  48         txbuf[1] = reg;
  49 
  50         return spi_write_then_read(spi, txbuf, 2, val, len);
  51 }
  52 
  53 static inline int b53_spi_clear_status(struct spi_device *spi)
  54 {
  55         unsigned int i;
  56         u8 rxbuf;
  57         int ret;
  58 
  59         for (i = 0; i < 10; i++) {
  60                 ret = b53_spi_read_reg(spi, B53_SPI_STATUS, &rxbuf, 1);
  61                 if (ret)
  62                         return ret;
  63 
  64                 if (!(rxbuf & B53_SPI_CMD_SPIF))
  65                         break;
  66 
  67                 mdelay(1);
  68         }
  69 
  70         if (i == 10)
  71                 return -EIO;
  72 
  73         return 0;
  74 }
  75 
  76 static inline int b53_spi_set_page(struct spi_device *spi, u8 page)
  77 {
  78         u8 txbuf[3];
  79 
  80         txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_WRITE;
  81         txbuf[1] = B53_SPI_PAGE_SELECT;
  82         txbuf[2] = page;
  83 
  84         return spi_write(spi, txbuf, sizeof(txbuf));
  85 }
  86 
  87 static inline int b53_prepare_reg_access(struct spi_device *spi, u8 page)
  88 {
  89         int ret = b53_spi_clear_status(spi);
  90 
  91         if (ret)
  92                 return ret;
  93 
  94         return b53_spi_set_page(spi, page);
  95 }
  96 
  97 static int b53_spi_prepare_reg_read(struct spi_device *spi, u8 reg)
  98 {
  99         u8 rxbuf;
 100         int retry_count;
 101         int ret;
 102 
 103         ret = b53_spi_read_reg(spi, reg, &rxbuf, 1);
 104         if (ret)
 105                 return ret;
 106 
 107         for (retry_count = 0; retry_count < 10; retry_count++) {
 108                 ret = b53_spi_read_reg(spi, B53_SPI_STATUS, &rxbuf, 1);
 109                 if (ret)
 110                         return ret;
 111 
 112                 if (rxbuf & B53_SPI_CMD_RACK)
 113                         break;
 114 
 115                 mdelay(1);
 116         }
 117 
 118         if (retry_count == 10)
 119                 return -EIO;
 120 
 121         return 0;
 122 }
 123 
 124 static int b53_spi_read(struct b53_device *dev, u8 page, u8 reg, u8 *data,
 125                         unsigned int len)
 126 {
 127         struct spi_device *spi = dev->priv;
 128         int ret;
 129 
 130         ret = b53_prepare_reg_access(spi, page);
 131         if (ret)
 132                 return ret;
 133 
 134         ret = b53_spi_prepare_reg_read(spi, reg);
 135         if (ret)
 136                 return ret;
 137 
 138         return b53_spi_read_reg(spi, B53_SPI_DATA, data, len);
 139 }
 140 
 141 static int b53_spi_read8(struct b53_device *dev, u8 page, u8 reg, u8 *val)
 142 {
 143         return b53_spi_read(dev, page, reg, val, 1);
 144 }
 145 
 146 static int b53_spi_read16(struct b53_device *dev, u8 page, u8 reg, u16 *val)
 147 {
 148         int ret = b53_spi_read(dev, page, reg, (u8 *)val, 2);
 149 
 150         if (!ret)
 151                 *val = le16_to_cpu(*val);
 152 
 153         return ret;
 154 }
 155 
 156 static int b53_spi_read32(struct b53_device *dev, u8 page, u8 reg, u32 *val)
 157 {
 158         int ret = b53_spi_read(dev, page, reg, (u8 *)val, 4);
 159 
 160         if (!ret)
 161                 *val = le32_to_cpu(*val);
 162 
 163         return ret;
 164 }
 165 
 166 static int b53_spi_read48(struct b53_device *dev, u8 page, u8 reg, u64 *val)
 167 {
 168         int ret;
 169 
 170         *val = 0;
 171         ret = b53_spi_read(dev, page, reg, (u8 *)val, 6);
 172         if (!ret)
 173                 *val = le64_to_cpu(*val);
 174 
 175         return ret;
 176 }
 177 
 178 static int b53_spi_read64(struct b53_device *dev, u8 page, u8 reg, u64 *val)
 179 {
 180         int ret = b53_spi_read(dev, page, reg, (u8 *)val, 8);
 181 
 182         if (!ret)
 183                 *val = le64_to_cpu(*val);
 184 
 185         return ret;
 186 }
 187 
 188 static int b53_spi_write8(struct b53_device *dev, u8 page, u8 reg, u8 value)
 189 {
 190         struct spi_device *spi = dev->priv;
 191         int ret;
 192         u8 txbuf[3];
 193 
 194         ret = b53_prepare_reg_access(spi, page);
 195         if (ret)
 196                 return ret;
 197 
 198         txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_WRITE;
 199         txbuf[1] = reg;
 200         txbuf[2] = value;
 201 
 202         return spi_write(spi, txbuf, sizeof(txbuf));
 203 }
 204 
 205 static int b53_spi_write16(struct b53_device *dev, u8 page, u8 reg, u16 value)
 206 {
 207         struct spi_device *spi = dev->priv;
 208         int ret;
 209         u8 txbuf[4];
 210 
 211         ret = b53_prepare_reg_access(spi, page);
 212         if (ret)
 213                 return ret;
 214 
 215         txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_WRITE;
 216         txbuf[1] = reg;
 217         put_unaligned_le16(value, &txbuf[2]);
 218 
 219         return spi_write(spi, txbuf, sizeof(txbuf));
 220 }
 221 
 222 static int b53_spi_write32(struct b53_device *dev, u8 page, u8 reg, u32 value)
 223 {
 224         struct spi_device *spi = dev->priv;
 225         int ret;
 226         u8 txbuf[6];
 227 
 228         ret = b53_prepare_reg_access(spi, page);
 229         if (ret)
 230                 return ret;
 231 
 232         txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_WRITE;
 233         txbuf[1] = reg;
 234         put_unaligned_le32(value, &txbuf[2]);
 235 
 236         return spi_write(spi, txbuf, sizeof(txbuf));
 237 }
 238 
 239 static int b53_spi_write48(struct b53_device *dev, u8 page, u8 reg, u64 value)
 240 {
 241         struct spi_device *spi = dev->priv;
 242         int ret;
 243         u8 txbuf[10];
 244 
 245         ret = b53_prepare_reg_access(spi, page);
 246         if (ret)
 247                 return ret;
 248 
 249         txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_WRITE;
 250         txbuf[1] = reg;
 251         put_unaligned_le64(value, &txbuf[2]);
 252 
 253         return spi_write(spi, txbuf, sizeof(txbuf) - 2);
 254 }
 255 
 256 static int b53_spi_write64(struct b53_device *dev, u8 page, u8 reg, u64 value)
 257 {
 258         struct spi_device *spi = dev->priv;
 259         int ret;
 260         u8 txbuf[10];
 261 
 262         ret = b53_prepare_reg_access(spi, page);
 263         if (ret)
 264                 return ret;
 265 
 266         txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_WRITE;
 267         txbuf[1] = reg;
 268         put_unaligned_le64(value, &txbuf[2]);
 269 
 270         return spi_write(spi, txbuf, sizeof(txbuf));
 271 }
 272 
 273 static const struct b53_io_ops b53_spi_ops = {
 274         .read8 = b53_spi_read8,
 275         .read16 = b53_spi_read16,
 276         .read32 = b53_spi_read32,
 277         .read48 = b53_spi_read48,
 278         .read64 = b53_spi_read64,
 279         .write8 = b53_spi_write8,
 280         .write16 = b53_spi_write16,
 281         .write32 = b53_spi_write32,
 282         .write48 = b53_spi_write48,
 283         .write64 = b53_spi_write64,
 284 };
 285 
 286 static int b53_spi_probe(struct spi_device *spi)
 287 {
 288         struct b53_device *dev;
 289         int ret;
 290 
 291         dev = b53_switch_alloc(&spi->dev, &b53_spi_ops, spi);
 292         if (!dev)
 293                 return -ENOMEM;
 294 
 295         if (spi->dev.platform_data)
 296                 dev->pdata = spi->dev.platform_data;
 297 
 298         ret = b53_switch_register(dev);
 299         if (ret)
 300                 return ret;
 301 
 302         spi_set_drvdata(spi, dev);
 303 
 304         return 0;
 305 }
 306 
 307 static int b53_spi_remove(struct spi_device *spi)
 308 {
 309         struct b53_device *dev = spi_get_drvdata(spi);
 310 
 311         if (dev)
 312                 b53_switch_remove(dev);
 313 
 314         return 0;
 315 }
 316 
 317 static struct spi_driver b53_spi_driver = {
 318         .driver = {
 319                 .name   = "b53-switch",
 320         },
 321         .probe  = b53_spi_probe,
 322         .remove = b53_spi_remove,
 323 };
 324 
 325 module_spi_driver(b53_spi_driver);
 326 
 327 MODULE_AUTHOR("Jonas Gorski <jogo@openwrt.org>");
 328 MODULE_DESCRIPTION("B53 SPI access driver");
 329 MODULE_LICENSE("Dual BSD/GPL");

/* [<][>][^][v][top][bottom][index][help] */