1*047980c5SChuanhong Guo // SPDX-License-Identifier: GPL-2.0 2*047980c5SChuanhong Guo // 3*047980c5SChuanhong Guo // SPI controller driver for Qualcomm Atheros AR934x/QCA95xx SoCs 4*047980c5SChuanhong Guo // 5*047980c5SChuanhong Guo // Copyright (C) 2020 Chuanhong Guo <gch981213@gmail.com> 6*047980c5SChuanhong Guo // 7*047980c5SChuanhong Guo // Based on spi-mt7621.c: 8*047980c5SChuanhong Guo // Copyright (C) 2011 Sergiy <piratfm@gmail.com> 9*047980c5SChuanhong Guo // Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org> 10*047980c5SChuanhong Guo // Copyright (C) 2014-2015 Felix Fietkau <nbd@nbd.name> 11*047980c5SChuanhong Guo 12*047980c5SChuanhong Guo #include <linux/clk.h> 13*047980c5SChuanhong Guo #include <linux/io.h> 14*047980c5SChuanhong Guo #include <linux/iopoll.h> 15*047980c5SChuanhong Guo #include <linux/kernel.h> 16*047980c5SChuanhong Guo #include <linux/module.h> 17*047980c5SChuanhong Guo #include <linux/of_device.h> 18*047980c5SChuanhong Guo #include <linux/spi/spi.h> 19*047980c5SChuanhong Guo 20*047980c5SChuanhong Guo #define DRIVER_NAME "spi-ar934x" 21*047980c5SChuanhong Guo 22*047980c5SChuanhong Guo #define AR934X_SPI_REG_FS 0x00 23*047980c5SChuanhong Guo #define AR934X_SPI_ENABLE BIT(0) 24*047980c5SChuanhong Guo 25*047980c5SChuanhong Guo #define AR934X_SPI_REG_IOC 0x08 26*047980c5SChuanhong Guo #define AR934X_SPI_IOC_INITVAL 0x70000 27*047980c5SChuanhong Guo 28*047980c5SChuanhong Guo #define AR934X_SPI_REG_CTRL 0x04 29*047980c5SChuanhong Guo #define AR934X_SPI_CLK_MASK GENMASK(5, 0) 30*047980c5SChuanhong Guo 31*047980c5SChuanhong Guo #define AR934X_SPI_DATAOUT 0x10 32*047980c5SChuanhong Guo 33*047980c5SChuanhong Guo #define AR934X_SPI_REG_SHIFT_CTRL 0x14 34*047980c5SChuanhong Guo #define AR934X_SPI_SHIFT_EN BIT(31) 35*047980c5SChuanhong Guo #define AR934X_SPI_SHIFT_CS(n) BIT(28 + (n)) 36*047980c5SChuanhong Guo #define AR934X_SPI_SHIFT_TERM 26 37*047980c5SChuanhong Guo #define AR934X_SPI_SHIFT_VAL(cs, term, count) \ 38*047980c5SChuanhong Guo (AR934X_SPI_SHIFT_EN | AR934X_SPI_SHIFT_CS(cs) | \ 39*047980c5SChuanhong Guo (term) << AR934X_SPI_SHIFT_TERM | (count)) 40*047980c5SChuanhong Guo 41*047980c5SChuanhong Guo #define AR934X_SPI_DATAIN 0x18 42*047980c5SChuanhong Guo 43*047980c5SChuanhong Guo struct ar934x_spi { 44*047980c5SChuanhong Guo struct spi_controller *ctlr; 45*047980c5SChuanhong Guo void __iomem *base; 46*047980c5SChuanhong Guo struct clk *clk; 47*047980c5SChuanhong Guo unsigned int clk_freq; 48*047980c5SChuanhong Guo }; 49*047980c5SChuanhong Guo 50*047980c5SChuanhong Guo static inline int ar934x_spi_clk_div(struct ar934x_spi *sp, unsigned int freq) 51*047980c5SChuanhong Guo { 52*047980c5SChuanhong Guo int div = DIV_ROUND_UP(sp->clk_freq, freq * 2) - 1; 53*047980c5SChuanhong Guo 54*047980c5SChuanhong Guo if (div < 0) 55*047980c5SChuanhong Guo return 0; 56*047980c5SChuanhong Guo else if (div > AR934X_SPI_CLK_MASK) 57*047980c5SChuanhong Guo return -EINVAL; 58*047980c5SChuanhong Guo else 59*047980c5SChuanhong Guo return div; 60*047980c5SChuanhong Guo } 61*047980c5SChuanhong Guo 62*047980c5SChuanhong Guo static int ar934x_spi_setup(struct spi_device *spi) 63*047980c5SChuanhong Guo { 64*047980c5SChuanhong Guo struct ar934x_spi *sp = spi_controller_get_devdata(spi->master); 65*047980c5SChuanhong Guo 66*047980c5SChuanhong Guo if ((spi->max_speed_hz == 0) || 67*047980c5SChuanhong Guo (spi->max_speed_hz > (sp->clk_freq / 2))) { 68*047980c5SChuanhong Guo spi->max_speed_hz = sp->clk_freq / 2; 69*047980c5SChuanhong Guo } else if (spi->max_speed_hz < (sp->clk_freq / 128)) { 70*047980c5SChuanhong Guo dev_err(&spi->dev, "spi clock is too low\n"); 71*047980c5SChuanhong Guo return -EINVAL; 72*047980c5SChuanhong Guo } 73*047980c5SChuanhong Guo 74*047980c5SChuanhong Guo return 0; 75*047980c5SChuanhong Guo } 76*047980c5SChuanhong Guo 77*047980c5SChuanhong Guo static int ar934x_spi_transfer_one_message(struct spi_controller *master, 78*047980c5SChuanhong Guo struct spi_message *m) 79*047980c5SChuanhong Guo { 80*047980c5SChuanhong Guo struct ar934x_spi *sp = spi_controller_get_devdata(master); 81*047980c5SChuanhong Guo struct spi_transfer *t = NULL; 82*047980c5SChuanhong Guo struct spi_device *spi = m->spi; 83*047980c5SChuanhong Guo unsigned long trx_done, trx_cur; 84*047980c5SChuanhong Guo int stat = 0; 85*047980c5SChuanhong Guo u8 term = 0; 86*047980c5SChuanhong Guo int div, i; 87*047980c5SChuanhong Guo u32 reg; 88*047980c5SChuanhong Guo const u8 *tx_buf; 89*047980c5SChuanhong Guo u8 *buf; 90*047980c5SChuanhong Guo 91*047980c5SChuanhong Guo m->actual_length = 0; 92*047980c5SChuanhong Guo list_for_each_entry(t, &m->transfers, transfer_list) { 93*047980c5SChuanhong Guo if (t->speed_hz) 94*047980c5SChuanhong Guo div = ar934x_spi_clk_div(sp, t->speed_hz); 95*047980c5SChuanhong Guo else 96*047980c5SChuanhong Guo div = ar934x_spi_clk_div(sp, spi->max_speed_hz); 97*047980c5SChuanhong Guo if (div < 0) { 98*047980c5SChuanhong Guo stat = -EIO; 99*047980c5SChuanhong Guo goto msg_done; 100*047980c5SChuanhong Guo } 101*047980c5SChuanhong Guo 102*047980c5SChuanhong Guo reg = ioread32(sp->base + AR934X_SPI_REG_CTRL); 103*047980c5SChuanhong Guo reg &= ~AR934X_SPI_CLK_MASK; 104*047980c5SChuanhong Guo reg |= div; 105*047980c5SChuanhong Guo iowrite32(reg, sp->base + AR934X_SPI_REG_CTRL); 106*047980c5SChuanhong Guo iowrite32(0, sp->base + AR934X_SPI_DATAOUT); 107*047980c5SChuanhong Guo 108*047980c5SChuanhong Guo for (trx_done = 0; trx_done < t->len; trx_done += 4) { 109*047980c5SChuanhong Guo trx_cur = t->len - trx_done; 110*047980c5SChuanhong Guo if (trx_cur > 4) 111*047980c5SChuanhong Guo trx_cur = 4; 112*047980c5SChuanhong Guo else if (list_is_last(&t->transfer_list, &m->transfers)) 113*047980c5SChuanhong Guo term = 1; 114*047980c5SChuanhong Guo 115*047980c5SChuanhong Guo if (t->tx_buf) { 116*047980c5SChuanhong Guo tx_buf = t->tx_buf + trx_done; 117*047980c5SChuanhong Guo reg = tx_buf[0]; 118*047980c5SChuanhong Guo for (i = 1; i < trx_cur; i++) 119*047980c5SChuanhong Guo reg = reg << 8 | tx_buf[i]; 120*047980c5SChuanhong Guo iowrite32(reg, sp->base + AR934X_SPI_DATAOUT); 121*047980c5SChuanhong Guo } 122*047980c5SChuanhong Guo 123*047980c5SChuanhong Guo reg = AR934X_SPI_SHIFT_VAL(spi->chip_select, term, 124*047980c5SChuanhong Guo trx_cur * 8); 125*047980c5SChuanhong Guo iowrite32(reg, sp->base + AR934X_SPI_REG_SHIFT_CTRL); 126*047980c5SChuanhong Guo stat = readl_poll_timeout( 127*047980c5SChuanhong Guo sp->base + AR934X_SPI_REG_SHIFT_CTRL, reg, 128*047980c5SChuanhong Guo !(reg & AR934X_SPI_SHIFT_EN), 0, 5); 129*047980c5SChuanhong Guo if (stat < 0) 130*047980c5SChuanhong Guo goto msg_done; 131*047980c5SChuanhong Guo 132*047980c5SChuanhong Guo if (t->rx_buf) { 133*047980c5SChuanhong Guo reg = ioread32(sp->base + AR934X_SPI_DATAIN); 134*047980c5SChuanhong Guo buf = t->rx_buf + trx_done; 135*047980c5SChuanhong Guo for (i = 0; i < trx_cur; i++) { 136*047980c5SChuanhong Guo buf[trx_cur - i - 1] = reg & 0xff; 137*047980c5SChuanhong Guo reg >>= 8; 138*047980c5SChuanhong Guo } 139*047980c5SChuanhong Guo } 140*047980c5SChuanhong Guo } 141*047980c5SChuanhong Guo m->actual_length += t->len; 142*047980c5SChuanhong Guo } 143*047980c5SChuanhong Guo 144*047980c5SChuanhong Guo msg_done: 145*047980c5SChuanhong Guo m->status = stat; 146*047980c5SChuanhong Guo spi_finalize_current_message(master); 147*047980c5SChuanhong Guo 148*047980c5SChuanhong Guo return 0; 149*047980c5SChuanhong Guo } 150*047980c5SChuanhong Guo 151*047980c5SChuanhong Guo static const struct of_device_id ar934x_spi_match[] = { 152*047980c5SChuanhong Guo { .compatible = "qca,ar934x-spi" }, 153*047980c5SChuanhong Guo {}, 154*047980c5SChuanhong Guo }; 155*047980c5SChuanhong Guo MODULE_DEVICE_TABLE(of, ar934x_spi_match); 156*047980c5SChuanhong Guo 157*047980c5SChuanhong Guo static int ar934x_spi_probe(struct platform_device *pdev) 158*047980c5SChuanhong Guo { 159*047980c5SChuanhong Guo struct spi_controller *ctlr; 160*047980c5SChuanhong Guo struct ar934x_spi *sp; 161*047980c5SChuanhong Guo void __iomem *base; 162*047980c5SChuanhong Guo struct clk *clk; 163*047980c5SChuanhong Guo int ret; 164*047980c5SChuanhong Guo 165*047980c5SChuanhong Guo base = devm_platform_ioremap_resource(pdev, 0); 166*047980c5SChuanhong Guo if (IS_ERR(base)) 167*047980c5SChuanhong Guo return PTR_ERR(base); 168*047980c5SChuanhong Guo 169*047980c5SChuanhong Guo clk = devm_clk_get(&pdev->dev, NULL); 170*047980c5SChuanhong Guo if (IS_ERR(clk)) { 171*047980c5SChuanhong Guo dev_err(&pdev->dev, "failed to get clock\n"); 172*047980c5SChuanhong Guo return PTR_ERR(clk); 173*047980c5SChuanhong Guo } 174*047980c5SChuanhong Guo 175*047980c5SChuanhong Guo ret = clk_prepare_enable(clk); 176*047980c5SChuanhong Guo if (ret) 177*047980c5SChuanhong Guo return ret; 178*047980c5SChuanhong Guo 179*047980c5SChuanhong Guo ctlr = spi_alloc_master(&pdev->dev, sizeof(*sp)); 180*047980c5SChuanhong Guo if (!ctlr) { 181*047980c5SChuanhong Guo dev_info(&pdev->dev, "failed to allocate spi controller\n"); 182*047980c5SChuanhong Guo return -ENOMEM; 183*047980c5SChuanhong Guo } 184*047980c5SChuanhong Guo 185*047980c5SChuanhong Guo /* disable flash mapping and expose spi controller registers */ 186*047980c5SChuanhong Guo iowrite32(AR934X_SPI_ENABLE, base + AR934X_SPI_REG_FS); 187*047980c5SChuanhong Guo /* restore pins to default state: CSn=1 DO=CLK=0 */ 188*047980c5SChuanhong Guo iowrite32(AR934X_SPI_IOC_INITVAL, base + AR934X_SPI_REG_IOC); 189*047980c5SChuanhong Guo 190*047980c5SChuanhong Guo ctlr->mode_bits = SPI_LSB_FIRST; 191*047980c5SChuanhong Guo ctlr->setup = ar934x_spi_setup; 192*047980c5SChuanhong Guo ctlr->transfer_one_message = ar934x_spi_transfer_one_message; 193*047980c5SChuanhong Guo ctlr->bits_per_word_mask = SPI_BPW_MASK(8); 194*047980c5SChuanhong Guo ctlr->dev.of_node = pdev->dev.of_node; 195*047980c5SChuanhong Guo ctlr->num_chipselect = 3; 196*047980c5SChuanhong Guo 197*047980c5SChuanhong Guo dev_set_drvdata(&pdev->dev, ctlr); 198*047980c5SChuanhong Guo 199*047980c5SChuanhong Guo sp = spi_controller_get_devdata(ctlr); 200*047980c5SChuanhong Guo sp->base = base; 201*047980c5SChuanhong Guo sp->clk = clk; 202*047980c5SChuanhong Guo sp->clk_freq = clk_get_rate(clk); 203*047980c5SChuanhong Guo sp->ctlr = ctlr; 204*047980c5SChuanhong Guo 205*047980c5SChuanhong Guo return devm_spi_register_controller(&pdev->dev, ctlr); 206*047980c5SChuanhong Guo } 207*047980c5SChuanhong Guo 208*047980c5SChuanhong Guo static int ar934x_spi_remove(struct platform_device *pdev) 209*047980c5SChuanhong Guo { 210*047980c5SChuanhong Guo struct spi_controller *ctlr; 211*047980c5SChuanhong Guo struct ar934x_spi *sp; 212*047980c5SChuanhong Guo 213*047980c5SChuanhong Guo ctlr = dev_get_drvdata(&pdev->dev); 214*047980c5SChuanhong Guo sp = spi_controller_get_devdata(ctlr); 215*047980c5SChuanhong Guo 216*047980c5SChuanhong Guo clk_disable_unprepare(sp->clk); 217*047980c5SChuanhong Guo 218*047980c5SChuanhong Guo return 0; 219*047980c5SChuanhong Guo } 220*047980c5SChuanhong Guo 221*047980c5SChuanhong Guo static struct platform_driver ar934x_spi_driver = { 222*047980c5SChuanhong Guo .driver = { 223*047980c5SChuanhong Guo .name = DRIVER_NAME, 224*047980c5SChuanhong Guo .of_match_table = ar934x_spi_match, 225*047980c5SChuanhong Guo }, 226*047980c5SChuanhong Guo .probe = ar934x_spi_probe, 227*047980c5SChuanhong Guo .remove = ar934x_spi_remove, 228*047980c5SChuanhong Guo }; 229*047980c5SChuanhong Guo 230*047980c5SChuanhong Guo module_platform_driver(ar934x_spi_driver); 231*047980c5SChuanhong Guo 232*047980c5SChuanhong Guo MODULE_DESCRIPTION("SPI controller driver for Qualcomm Atheros AR934x/QCA95xx"); 233*047980c5SChuanhong Guo MODULE_AUTHOR("Chuanhong Guo <gch981213@gmail.com>"); 234*047980c5SChuanhong Guo MODULE_LICENSE("GPL v2"); 235*047980c5SChuanhong Guo MODULE_ALIAS("platform:" DRIVER_NAME); 236