Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  *
0003  *   Copyright (c) 2011, 2012, Qualcomm Atheros Communications Inc.
0004  *   Copyright (c) 2014, I2SE GmbH
0005  *
0006  *   Permission to use, copy, modify, and/or distribute this software
0007  *   for any purpose with or without fee is hereby granted, provided
0008  *   that the above copyright notice and this permission notice appear
0009  *   in all copies.
0010  *
0011  *   THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
0012  *   WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
0013  *   WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
0014  *   THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
0015  *   CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
0016  *   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
0017  *   NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
0018  *   CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0019  *
0020  */
0021 
0022 /*   This module implements the Qualcomm Atheros SPI protocol for
0023  *   kernel-based SPI device.
0024  */
0025 
0026 #include <linux/kernel.h>
0027 #include <linux/netdevice.h>
0028 #include <linux/spi/spi.h>
0029 
0030 #include "qca_7k.h"
0031 
0032 void
0033 qcaspi_spi_error(struct qcaspi *qca)
0034 {
0035     if (qca->sync != QCASPI_SYNC_READY)
0036         return;
0037 
0038     netdev_err(qca->net_dev, "spi error\n");
0039     qca->sync = QCASPI_SYNC_UNKNOWN;
0040     qca->stats.spi_err++;
0041 }
0042 
0043 int
0044 qcaspi_read_register(struct qcaspi *qca, u16 reg, u16 *result)
0045 {
0046     __be16 rx_data;
0047     __be16 tx_data;
0048     struct spi_transfer transfer[2];
0049     struct spi_message msg;
0050     int ret;
0051 
0052     memset(transfer, 0, sizeof(transfer));
0053 
0054     spi_message_init(&msg);
0055 
0056     tx_data = cpu_to_be16(QCA7K_SPI_READ | QCA7K_SPI_INTERNAL | reg);
0057     *result = 0;
0058 
0059     transfer[0].tx_buf = &tx_data;
0060     transfer[0].len = QCASPI_CMD_LEN;
0061     transfer[1].rx_buf = &rx_data;
0062     transfer[1].len = QCASPI_CMD_LEN;
0063 
0064     spi_message_add_tail(&transfer[0], &msg);
0065 
0066     if (qca->legacy_mode) {
0067         spi_sync(qca->spi_dev, &msg);
0068         spi_message_init(&msg);
0069     }
0070     spi_message_add_tail(&transfer[1], &msg);
0071     ret = spi_sync(qca->spi_dev, &msg);
0072 
0073     if (!ret)
0074         ret = msg.status;
0075 
0076     if (ret)
0077         qcaspi_spi_error(qca);
0078     else
0079         *result = be16_to_cpu(rx_data);
0080 
0081     return ret;
0082 }
0083 
0084 static int
0085 __qcaspi_write_register(struct qcaspi *qca, u16 reg, u16 value)
0086 {
0087     __be16 tx_data[2];
0088     struct spi_transfer transfer[2];
0089     struct spi_message msg;
0090     int ret;
0091 
0092     memset(&transfer, 0, sizeof(transfer));
0093 
0094     spi_message_init(&msg);
0095 
0096     tx_data[0] = cpu_to_be16(QCA7K_SPI_WRITE | QCA7K_SPI_INTERNAL | reg);
0097     tx_data[1] = cpu_to_be16(value);
0098 
0099     transfer[0].tx_buf = &tx_data[0];
0100     transfer[0].len = QCASPI_CMD_LEN;
0101     transfer[1].tx_buf = &tx_data[1];
0102     transfer[1].len = QCASPI_CMD_LEN;
0103 
0104     spi_message_add_tail(&transfer[0], &msg);
0105     if (qca->legacy_mode) {
0106         spi_sync(qca->spi_dev, &msg);
0107         spi_message_init(&msg);
0108     }
0109     spi_message_add_tail(&transfer[1], &msg);
0110     ret = spi_sync(qca->spi_dev, &msg);
0111 
0112     if (!ret)
0113         ret = msg.status;
0114 
0115     if (ret)
0116         qcaspi_spi_error(qca);
0117 
0118     return ret;
0119 }
0120 
0121 int
0122 qcaspi_write_register(struct qcaspi *qca, u16 reg, u16 value, int retry)
0123 {
0124     int ret, i = 0;
0125     u16 confirmed;
0126 
0127     do {
0128         ret = __qcaspi_write_register(qca, reg, value);
0129         if (ret)
0130             return ret;
0131 
0132         if (!retry)
0133             return 0;
0134 
0135         ret = qcaspi_read_register(qca, reg, &confirmed);
0136         if (ret)
0137             return ret;
0138 
0139         ret = confirmed != value;
0140         if (!ret)
0141             return 0;
0142 
0143         i++;
0144         qca->stats.write_verify_failed++;
0145 
0146     } while (i <= retry);
0147 
0148     return ret;
0149 }