123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813 |
- /*
- * Copyright (C) 2016 MediaTek Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
- */
- #include <linux/spi/spi.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/types.h>
- #include <linux/device.h>
- #include <linux/delay.h>
- #include <linux/platform_data/spi-mt65xx.h>
- #include <linux/dma-mapping.h>
- #include <linux/sched.h>
- #include <linux/kthread.h>
- #include <linux/clk.h>
- #if 0
- /* #ifdef CONFIG_TRUSTONIC_TEE_SUPPORT */
- #define SPI_TRUSTONIC_TEE_SUPPORT
- #endif
- #ifdef SPI_TRUSTONIC_TEE_SUPPORT
- #include <mobicore_driver_api.h>
- #include <tlspi_Api.h>
- #endif
- static struct spi_device *spi_test;
- u32 speed = 10000000;
- struct mtk_spi {
- void __iomem *base;
- u32 state;
- int pad_num;
- u32 *pad_sel;
- struct clk *parent_clk, *sel_clk, *spi_clk;
- struct spi_transfer *cur_transfer;
- u32 xfer_len;
- u32 num_xfered;
- struct scatterlist *tx_sgl, *rx_sgl;
- u32 tx_sgl_len, rx_sgl_len;
- const struct mtk_spi_compatible *dev_comp;
- };
- static struct mtk_chip_config mtk_test_chip_info = {
- .rx_mlsb = 0,
- .tx_mlsb = 0,
- .sample_sel = 0,
- .cs_setuptime = 0,
- .cs_holdtime = 0,
- .cs_idletime = 0,
- .deassert_mode = 0,
- .tick_delay = 0,
- };
- #define SPI_CFG0_REG 0x0000
- #define SPI_CFG1_REG 0x0004
- #define SPI_TX_SRC_REG 0x0008
- #define SPI_RX_DST_REG 0x000c
- #define SPI_TX_DATA_REG 0x0010
- #define SPI_RX_DATA_REG 0x0014
- #define SPI_CMD_REG 0x0018
- #define SPI_STATUS0_REG 0x001c
- #define SPI_STATUS1_REG 0x0020
- #define SPI_PAD_SEL_REG 0x0024
- #define SPI_CFG2_REG 0x0028
- #define SPI_TX_SRC_REG_64 0x002c
- #define SPI_RX_DST_REG_64 0x0030
- #define SPI_CFG1_CS_IDLE_OFFSET 0
- #define SPI_CFG1_GET_TICK_DLY_OFFSET 29
- #ifdef SPI_TRUSTONIC_TEE_SUPPORT
- #define DEFAULT_HANDLES_NUM (64)
- #define MAX_OPEN_SESSIONS (0xffffffff - 1)
- /*
- * Trustlet UUID.
- */
- u8 spi_uuid[10][16] = {
- {0x09, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x09, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x09, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x09, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x09, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x09, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x09, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x09, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x09, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x09, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00} };
- static struct mc_session_handle secspi_session = { 0 };
- static u32 secspi_session_ref;
- static u32 secspi_devid = MC_DEVICE_ID_DEFAULT;
- static tciSpiMessage_t *secspi_tci;
- static DEFINE_MUTEX(secspi_lock);
- int secspi_session_open(u32 spinum)
- {
- enum mc_result mc_ret = MC_DRV_OK;
- mutex_lock(&secspi_lock);
- pr_info("%s() start\n", __func__);
- do {
- /* sessions reach max numbers ? */
- if (secspi_session_ref > MAX_OPEN_SESSIONS) {
- pr_notice("%s() err: secspi_session(0x%x)>MAX(0x%x)\n",
- __func__, secspi_session_ref, MAX_OPEN_SESSIONS);
- break;
- }
- if (secspi_session_ref > 0) {
- secspi_session_ref++;
- break;
- }
- /* open device */
- mc_ret = mc_open_device(secspi_devid);
- if (mc_ret != MC_DRV_OK) {
- pr_notice("%s() mc_open_device failed: %d\n", __func__,
- mc_ret);
- break;
- }
- /* allocating WSM for DCI */
- mc_ret = mc_malloc_wsm(secspi_devid, 0,
- sizeof(tciSpiMessage_t), (uint8_t **) &secspi_tci, 0);
- if (mc_ret != MC_DRV_OK) {
- pr_notice("%s() mc_malloc_wsm failed: %d\n", __func__,
- mc_ret);
- mc_close_device(secspi_devid);
- break;
- }
- /* open session */
- secspi_session.device_id = secspi_devid;
- mc_ret = mc_open_session(&secspi_session,
- (struct mc_uuid_t *)&spi_uuid[spinum][0],
- (uint8_t *)secspi_tci, sizeof(tciSpiMessage_t));
- if (mc_ret != MC_DRV_OK) {
- pr_notice("%s() mc_open_session fail: %d\n", __func__,
- mc_ret);
- mc_free_wsm(secspi_devid, (uint8_t *) secspi_tci);
- mc_close_device(secspi_devid);
- secspi_tci = NULL;
- break;
- }
- secspi_session_ref = 1;
- } while (0);
- mutex_unlock(&secspi_lock);
- if (mc_ret != MC_DRV_OK) {
- pr_notice("%s() Done. Fail! ret=%d, ref=%d\n", __func__,
- mc_ret, secspi_session_ref);
- return -ENXIO;
- }
- pr_info("%s() Done. Success! ret=%d, ref=%d\n", __func__, mc_ret,
- secspi_session_ref);
- return 0;
- }
- static int secspi_session_close(void)
- {
- enum mc_result mc_ret = MC_DRV_OK;
- mutex_lock(&secspi_lock);
- do {
- /* session is already closed ? */
- if (secspi_session_ref == 0) {
- pr_notice("%s() spi_session already closed\n",
- __func__);
- break;
- }
- if (secspi_session_ref > 1) {
- secspi_session_ref--;
- break;
- }
- /* close session */
- mc_ret = mc_close_session(&secspi_session);
- if (mc_ret != MC_DRV_OK) {
- pr_notice("%s() mc_close_session failed: %d\n",
- __func__, mc_ret);
- break;
- }
- /* free WSM for DCI */
- mc_ret = mc_free_wsm(secspi_devid, (uint8_t *) secspi_tci);
- if (mc_ret != MC_DRV_OK) {
- pr_notice("%s() mc_free_wsm failed: %d\n", __func__,
- mc_ret);
- break;
- }
- secspi_tci = NULL;
- secspi_session_ref = 0;
- /* close device */
- mc_ret = mc_close_device(secspi_devid);
- if (mc_ret != MC_DRV_OK)
- pr_notice("%s() mc_close_device failed: %d\n",
- __func__, mc_ret);
- } while (0);
- mutex_unlock(&secspi_lock);
- if (mc_ret != MC_DRV_OK) {
- pr_notice("%s() Done. Fail! ret=%d, ref=%d\n", __func__,
- mc_ret, secspi_session_ref);
- return -ENXIO;
- }
- pr_info("%s() Done. Success! ret=%d, ref=%d\n", __func__, mc_ret,
- secspi_session_ref);
- return 0;
- }
- void secspi_enable_clk(struct spi_device *spidev)
- {
- int ret;
- struct spi_master *master;
- struct mtk_spi *ms;
- master = spidev->master;
- ms = spi_master_get_devdata(master);
- /*
- * prepare the clock source
- */
- ret = clk_prepare_enable(ms->spi_clk);
- }
- int secspi_execute(u32 cmd, tciSpiMessage_t *param)
- {
- enum mc_result mc_ret;
- pr_info("%s() start.\n", __func__);
- mutex_lock(&secspi_lock);
- if (secspi_tci == NULL) {
- mutex_unlock(&secspi_lock);
- pr_notice("%s() secspi_tci not exist\n", __func__);
- return -ENODEV;
- }
- /*set transfer data para */
- if (param == NULL) {
- pr_notice("%s() parameter is NULL !!\n", __func__);
- } else {
- secspi_tci->tx_buf = param->tx_buf;
- secspi_tci->rx_buf = param->rx_buf;
- secspi_tci->len = param->len;
- secspi_tci->is_dma_used = param->is_dma_used;
- secspi_tci->tx_dma = param->tx_dma;
- secspi_tci->rx_dma = param->rx_dma;
- secspi_tci->tl_chip_config = param->tl_chip_config;
- }
- secspi_tci->cmd_spi.header.commandId = (tciCommandId_t) cmd;
- secspi_tci->cmd_spi.len = 0;
- /* enable_clock(MT_CG_PERI_SPI0, "spi"); */
- /* enable_clk(ms); */
- mc_ret = mc_notify(&secspi_session);
- if (mc_ret != MC_DRV_OK) {
- pr_notice("%s() mc_notify failed: %d", __func__, mc_ret);
- goto exit;
- }
- mc_ret = mc_wait_notification(&secspi_session, -1);
- if (mc_ret != MC_DRV_OK) {
- pr_notice("%s() SPI mc_wait_notification failed: %d", __func__,
- mc_ret);
- goto exit;
- }
- exit:
- mutex_unlock(&secspi_lock);
- if (mc_ret != MC_DRV_OK) {
- pr_notice("%s() Done. Fail. ret:%d\n", __func__, mc_ret);
- return -ENOSPC;
- }
- pr_info("%s() Done. Success. ret:%d\n", __func__, mc_ret);
- return 0;
- }
- /*used for REE to detach IRQ of TEE*/
- void spi_detach_irq_tee(u32 spinum)
- {
- secspi_session_open(spinum);
- secspi_execute(2, NULL);
- pr_info("%s() Done.\n", __func__);
- }
- #endif
- void mt_spi_disable_master_clk(struct spi_device *spidev)
- {
- struct mtk_spi *ms;
- ms = spi_master_get_devdata(spidev->master);
- clk_disable_unprepare(ms->spi_clk);
- }
- EXPORT_SYMBOL(mt_spi_disable_master_clk);
- void mt_spi_enable_master_clk(struct spi_device *spidev)
- {
- int ret;
- struct mtk_spi *ms;
- ms = spi_master_get_devdata(spidev->master);
- ret = clk_prepare_enable(ms->spi_clk);
- }
- EXPORT_SYMBOL(mt_spi_enable_master_clk);
- static int spi_setup_xfer(struct device *dev, struct spi_transfer *xfer,
- u32 len, u32 flag)
- {
- u32 tx_buffer = 0x12345678;
- u32 cnt, i;
- xfer->speed_hz = speed;
- pr_info("%s() flag:%d speed:%d\n", __func__, flag, xfer->speed_hz);
- /* Instead of using kzalloc, if using below
- * dma_alloc_coherent to allocate tx_dma/rx_dma, remember:
- * 1. remove kfree in spi_recv_check_all, otherwise KE reboot
- * 2. set msg.is_dma_mapped = 1 before calling spi_sync();
- */
- if ((xfer->tx_buf == NULL) || (xfer->rx_buf == NULL))
- return -1;
- cnt = (len%4)?(len/4 + 1):(len/4);
- if (flag == 0)
- for (i = 0; i < cnt; i++)
- *((u32 *)xfer->tx_buf + i) = tx_buffer;
- else if (flag == 1)
- for (i = 0; i < cnt; i++)
- *((u32 *)xfer->tx_buf + i) = tx_buffer + i;
- else
- return -EINVAL;
- return 0;
- }
- static int spi_recv_check(struct spi_device *spi, struct spi_message *msg)
- {
- struct mtk_chip_config *chip_config;
- struct spi_transfer *xfer;
- u32 i, err = 0;
- int j;
- u8 t, rec_cac;
- chip_config = (struct mtk_chip_config *) spi->controller_data;
- list_for_each_entry(xfer, &msg->transfers, transfer_list) {
- if (!xfer) {
- pr_notice("%s() rv msg is NULL.\n", __func__);
- return -1;
- }
- pr_info("%s xfer->len:%d chip_config->tx_mlsb:%d rx_mlsb:%d\n",
- __func__, xfer->len, chip_config->tx_mlsb,
- chip_config->rx_mlsb);
- for (i = 0; i < xfer->len; i++) {
- if (chip_config->tx_mlsb ^ chip_config->rx_mlsb) {
- rec_cac = 0;
- for (j = 7; j >= 0; j--) {
- t = *((u8 *)xfer->tx_buf + i) & (1<<j);
- t = (t >> j) << (7-j);
- rec_cac |= t;
- }
- } else
- rec_cac = *((u8 *) xfer->tx_buf + i);
- if (*((u8 *) xfer->rx_buf + i) != rec_cac) {
- pr_notice("%s() tx xfer %d is:%x\n", __func__,
- i, *((u8 *) xfer->tx_buf + i));
- pr_notice("%s() rx xfer %d is:%x\n", __func__,
- i, *((u8 *) xfer->rx_buf + i));
- err++;
- }
- }
- }
- pr_info("%s() Done. error %d,actual xfer len:%d\n", __func__, err,
- msg->actual_length);
- return err;
- }
- static ssize_t spi_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct spi_device *spi;
- struct mtk_spi *mdata = NULL;
- struct mtk_chip_config *chip_config;
- u32 cs_idletime, pad_sel;
- int cpol, cpha, tx_mlsb, rx_mlsb;
- int sample_sel, tckdly;
- u32 reg_val;
- int dump_all, dump;
- int index;
- #if 0
- /* #ifdef CONFIG_TRUSTONIC_TEE_SUPPORT */
- u32 spinum;
- #endif
- spi = container_of(dev, struct spi_device, dev);
- pr_info("%s() SPIDEV name is:%s\n", __func__, spi->modalias);
- chip_config = (struct mtk_chip_config *) spi->controller_data;
- if (!chip_config) {
- pr_notice("%s() chip_config is NULL.\n", __func__);
- chip_config = kzalloc(sizeof(struct mtk_chip_config),
- GFP_KERNEL);
- if (!chip_config)
- return -ENOMEM;
- }
- if (!buf) {
- pr_notice("%s() buf is NULL.Exit!\n", __func__);
- goto out;
- }
- #if 0
- /* #ifdef CONFIG_TRUSTONIC_TEE_SUPPORT */
- if (!strncmp(buf, "send", 4)) {
- if (sscanf(buf + 4, "%d", &spinum) == 1) {
- pr_info("%s() start to access TL SPI driver.\n",
- __func__);
- secspi_session_open(spinum);
- secspi_enable_clk(spi);
- secspi_execute(1, NULL);
- secspi_session_close();
- pr_info("%s() secspi_execute 1 finished!\n", __func__);
- }
- } else if (!strncmp(buf, "config", 6)) {
- if (sscanf(buf + 6, "%d", &spinum) == 1) {
- pr_info("start to access TL SPI driver.\n");
- secspi_session_open(spinum);
- secspi_execute(2, NULL);
- secspi_session_close();
- pr_info("secspi_execute 2 finished!!!\n");
- }
- } else if (!strncmp(buf, "debug", 5)) {
- if (sscanf(buf + 5, "%d", &spinum) == 1) {
- pr_info("start to access TL SPI driver.\n");
- secspi_session_open(spinum);
- secspi_execute(3, NULL);
- secspi_session_close();
- pr_info("secspi_execute 3 finished!!!\n");
- }
- } else if (!strncmp(buf, "test", 4)) {
- if (sscanf(buf + 4, "%d", &spinum) == 1) {
- pr_info("start to access TL SPI driver.\n");
- secspi_session_open(spinum);
- secspi_execute(4, NULL);
- secspi_session_close();
- pr_info("secspi_execute 4 finished!!!\n");
- }
- }
- #endif
- else if (!strncmp(buf, "-w", 2))
- goto set;
- else
- goto out;
- set:
- buf += 3;
- mdata = spi_master_get_devdata(spi->master);
- mt_spi_enable_master_clk(spi);
- if (!strncmp(buf, "setuptime=", 10))
- pr_info("%s() setuptime cannot be set by cmd.\n", __func__);
- else if (!strncmp(buf, "holdtime=", 9))
- pr_info("%s() holdtime cannot be set by cmd.\n", __func__);
- else if (!strncmp(buf, "high_time=", 10))
- pr_info("%s() high_time cannot be set by cmd.\n", __func__);
- else if (!strncmp(buf, "low_time=", 9))
- pr_info("%s() low_time cannot be set by cmd.\n", __func__);
- else if (!strncmp(buf, "tckdly=", 7)) {
- if (sscanf(buf+7, "%d", &tckdly) == 1) {
- pr_info("%s() set tckdly=%d to SPI_CFG1_REG.\n",
- __func__, tckdly);
- reg_val = readl(mdata->base + SPI_CFG1_REG);
- reg_val &= 0x1FFFFFFF;
- reg_val |= (tckdly << SPI_CFG1_GET_TICK_DLY_OFFSET);
- writel(reg_val, mdata->base + SPI_CFG1_REG);
- reg_val = readl(mdata->base + SPI_CFG1_REG);
- pr_info("%s() now SPI_CFG1_REG=0x%x.\n", __func__,
- reg_val);
- }
- } else if (!strncmp(buf, "cs_idletime=", 12)) {
- if (sscanf(buf+12, "%d", &cs_idletime) == 1) {
- pr_info("%s() set cs_idletime=%d to SPI_CFG1_REG\n",
- __func__, cs_idletime);
- reg_val = readl(mdata->base + SPI_CFG1_REG);
- reg_val &= 0xFFFFFF00;
- reg_val |= (cs_idletime << SPI_CFG1_CS_IDLE_OFFSET);
- writel(reg_val, mdata->base + SPI_CFG1_REG);
- reg_val = readl(mdata->base + SPI_CFG1_REG);
- pr_info("%s() now SPI_CFG1_REG=0x%x.\n", __func__,
- reg_val);
- }
- } else if (!strncmp(buf, "cpol=", 5)) {
- if (sscanf(buf+5, "%d", &cpol) == 1) {
- pr_info("%s() Set cpol=%d to spi->mode.\n", __func__,
- cpol);
- spi->mode &= 0xFD;
- spi->mode |= cpol<<1;
- pr_info("%s() mow spi->mode:0x%.4x\n", __func__,
- spi->mode);
- }
- } else if (!strncmp(buf, "cpha=", 5)) {
- if (sscanf(buf+5, "%d", &cpha) == 1) {
- pr_info("%s() Set cpha=%d to spi->mode.\n", __func__,
- cpha);
- spi->mode &= 0xFE;
- spi->mode |= cpha;
- pr_info("%s() mow spi->mode:0x%.4x\n", __func__,
- spi->mode);
- }
- } else if (!strncmp(buf, "tx_mlsb=", 8)) {
- if (sscanf(buf+8, "%d", &tx_mlsb) == 1) {
- pr_info("%s() Set tx_mlsb=%d to chip_config\n",
- __func__, tx_mlsb);
- chip_config->tx_mlsb = tx_mlsb;
- }
- } else if (!strncmp(buf, "rx_mlsb=", 8)) {
- if (sscanf(buf+8, "%d", &rx_mlsb) == 1) {
- pr_info("%s() Set rx_mlsb=%d to chip_config\n",
- __func__, rx_mlsb);
- chip_config->rx_mlsb = rx_mlsb;
- }
- } else if (!strncmp(buf, "tx_endian=", 10))
- pr_info("%s() tx_endian cannot be set.See __LTTTLE_ENDIAN\n",
- __func__);
- else if (!strncmp(buf, "rx_endian=", 10))
- pr_info("%s() rx_endian cannot be set.See __LTTTLE_ENDIAN\n",
- __func__);
- else if (!strncmp(buf, "pause=", 6))
- pr_info("%s() pause cannot be set due to sw auto select\n",
- __func__);
- else if (!strncmp(buf, "deassert=", 9))
- pr_info("%s() deassert cannot be set, sw default disable\n",
- __func__);
- else if (!strncmp(buf, "sample_sel=", 11)) {
- if (sscanf(buf + 11, "%d", &sample_sel) == 1) {
- pr_info("%s() Set sample_sel=%d to chip_config\n",
- __func__, sample_sel);
- chip_config->sample_sel = sample_sel;
- }
- } else if (!strncmp(buf, "pad_sel=", 8)) {
- if (sscanf(buf + 8, "%d", &pad_sel) == 1) {
- pr_info("%s() Set pad select=%d to mdata->pad_sel.\n",
- __func__, pad_sel);
- mdata->pad_sel[spi->chip_select] = pad_sel;
- }
- } else if (!strncmp(buf, "speed=", 6)) {
- if (sscanf(buf + 6, "%d", &speed) == 1)
- pr_info("%s() Set speed=%d as global parameter.\n",
- __func__, speed);
- } else if (!strncmp(buf, "dump_all=", 9)) {
- if (sscanf(buf + 9, "%d", &dump_all) == 1) {
- pr_info("%s() dump all register.\n", __func__);
- pr_info("||* spi_dump_reg *******************||\n");
- pr_info("cfg0:0x%.8x\n",
- readl(mdata->base + SPI_CFG0_REG));
- pr_info("cfg1:0x%.8x\n",
- readl(mdata->base + SPI_CFG1_REG));
- pr_info("tx_s:0x%.8x\n",
- readl(mdata->base + SPI_TX_SRC_REG));
- pr_info("rx_d:0x%.8x\n",
- readl(mdata->base + SPI_RX_DST_REG));
- pr_info("tx_data:0x%.8x\n",
- readl(mdata->base + SPI_TX_DATA_REG));
- pr_info("rx_data:0x%.8x\n",
- readl(mdata->base + SPI_RX_DATA_REG));
- pr_info("cmd :0x%.8x\n",
- readl(mdata->base + SPI_CMD_REG));
- pr_info("status0:0x%.8x\n",
- readl(mdata->base + SPI_STATUS0_REG));
- pr_info("status1:0x%.8x\n",
- readl(mdata->base + SPI_STATUS1_REG));
- pr_info("pad_sel:0x%.8x\n",
- readl(mdata->base + SPI_PAD_SEL_REG));
- pr_info("cfg2:0x%.8x\n",
- readl(mdata->base + SPI_CFG2_REG));
- pr_info("tx_s64:0x%.8x\n",
- readl(mdata->base + SPI_TX_SRC_REG_64));
- pr_info("rx_d64:0x%.8x\n",
- readl(mdata->base + SPI_RX_DST_REG_64));
- pr_info("||*****************************************||\n");
- }
- } else if (!strncmp(buf, "dump=", 5)) {
- if (sscanf(buf + 5, "%d", &dump) == 1) {
- pr_info("%s() dump TX FIFO.\n", __func__);
- for (index = 1; index <= 8; index++)
- pr_info("%d tx_data:0x%.8x\n",
- index, readl(mdata->base + SPI_TX_DATA_REG));
- pr_info("%s() dump RX FIFO.\n", __func__);
- for (index = 1; index <= 8; index++)
- pr_info("%d rx_data:0x%.8x\n",
- index, readl(mdata->base + SPI_RX_DATA_REG));
- }
- } else {
- pr_notice("%s() Wrong parameters.Do nothing.\n", __func__);
- mt_spi_disable_master_clk(spi);
- goto out;
- }
- mt_spi_disable_master_clk(spi);
- out:
- if (!spi->controller_data)
- kfree(chip_config);
- return count;
- }
- static ssize_t
- spi_msg_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
- {
- int ret = 0;
- struct spi_device *spi;
- struct spi_transfer transfer = {0,};
- struct spi_message msg;
- u32 len = 4;
- spi = container_of(dev, struct spi_device, dev);
- if (unlikely(!spi)) {
- pr_notice("%s() spi device is invalid\n", __func__);
- goto out;
- }
- if (unlikely(!buf)) {
- pr_notice("%s() buf is invalid\n", __func__);
- goto out;
- }
- spi_message_init(&msg);
- if (strncmp(buf, "-func", 5)) {
- pr_notice("%s() Wrong parameters.Do nothing.\n", __func__);
- ret = -1;
- goto out;
- }
- buf += 6;
- if (!strncmp(buf, "len=", 4) && 1 == sscanf(buf + 4, "%d", &len)) {
- pr_info("%s() start transfer,dataLen=%d.-----------------\n",
- __func__, len);
- transfer.len = len;
- transfer.tx_buf = kzalloc(len, GFP_KERNEL);
- transfer.rx_buf = kzalloc(len, GFP_KERNEL);
- pr_info("%s() transfer.tx_buf:%p, transfer.rx_buf:%p\n",
- __func__, transfer.tx_buf, transfer.rx_buf);
- spi_setup_xfer(&spi->dev, &transfer, len, 1);
- spi_message_add_tail(&transfer, &msg);
- ret = spi_sync(spi, &msg);
- if (ret < 0) {
- pr_notice("%s() spi_sync err:%d\n", __func__, ret);
- } else {
- ret = spi_recv_check(spi, &msg);
- kfree(transfer.tx_buf);
- kfree(transfer.rx_buf);
- if (ret != 0) {
- ret = -ret;
- pr_notice("%s Message transfer err:%d\n",
- __func__, ret);
- goto out;
- }
- }
- pr_info("%s() spi transfer Done.-----------------\n",
- __func__);
- }
- ret = count;
- out:
- return count;
- //return ret;
- }
- static DEVICE_ATTR(spi, 0200, NULL, spi_store);
- static DEVICE_ATTR(spi_msg, 0200, NULL, spi_msg_store);
- static struct device_attribute *spi_attribute[] = {
- &dev_attr_spi,
- &dev_attr_spi_msg,
- };
- static int spi_create_attribute(struct device *dev)
- {
- int num, idx;
- int err = 0;
- num = (int)ARRAY_SIZE(spi_attribute);
- for (idx = 0; idx < num; idx++) {
- err = device_create_file(dev, spi_attribute[idx]);
- if (err)
- break;
- }
- return err;
- }
- static void spi_remove_attribute(struct device *dev)
- {
- int num, idx;
- num = (int)ARRAY_SIZE(spi_attribute);
- for (idx = 0; idx < num; idx++)
- device_remove_file(dev, spi_attribute[idx]);
- }
- static int spi_test_remove(struct spi_device *spi)
- {
- pr_info("%s().\n", __func__);
- spi_remove_attribute(&spi->dev);
- return 0;
- }
- static int spi_test_probe(struct spi_device *spi)
- {
- pr_info("%s() enter.\n", __func__);
- spi_test = spi;
- spi->mode = SPI_MODE_3;
- spi->bits_per_word = 8;
- spi->controller_data = (void *)&mtk_test_chip_info;
- return spi_create_attribute(&spi->dev);
- }
- struct spi_device_id spi_id_table[] = {
- {"spi-ut", 0},
- {},
- };
- static const struct of_device_id spidev_dt_ids[] = {
- { .compatible = "mediatek,spi-mt65xx-test" },
- {},
- };
- MODULE_DEVICE_TABLE(of, spidev_dt_ids);
- static struct spi_driver spi_test_driver = {
- .driver = {
- .name = "test_spi",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- .of_match_table = spidev_dt_ids,
- },
- .probe = spi_test_probe,
- .remove = spi_test_remove,
- .id_table = spi_id_table,
- };
- static int __init spi_dev_init(void)
- {
- pr_info("%s().\n", __func__);
- return spi_register_driver(&spi_test_driver);
- }
- static void __exit spi_test_exit(void)
- {
- pr_info("%s().\n", __func__);
- spi_unregister_driver(&spi_test_driver);
- }
- module_init(spi_dev_init);
- module_exit(spi_test_exit);
- MODULE_DESCRIPTION("mt SPI test device driver");
- MODULE_AUTHOR("ZH Chen <zh.chen@mediatek.com>");
- MODULE_LICENSE("GPL");
|