spi-rb4xx.c 5.19 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-only
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * SPI controller driver for the Mikrotik RB4xx boards
 *
 * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
 * Copyright (C) 2015 Bert Vermeulen <bert@biot.com>
 *
 * This file was based on the patches for Linux 2.6.27.39 published by
 * MikroTik for their RouterBoard 4xx series devices.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/spi/spi.h>
17
#include <linux/of.h>
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

#include <asm/mach-ath79/ar71xx_regs.h>

struct rb4xx_spi {
	void __iomem *base;
	struct clk *clk;
};

static inline u32 rb4xx_read(struct rb4xx_spi *rbspi, u32 reg)
{
	return __raw_readl(rbspi->base + reg);
}

static inline void rb4xx_write(struct rb4xx_spi *rbspi, u32 reg, u32 value)
{
	__raw_writel(value, rbspi->base + reg);
}

static inline void do_spi_clk(struct rb4xx_spi *rbspi, u32 spi_ioc, int value)
{
	u32 regval;

	regval = spi_ioc;
	if (value & BIT(0))
		regval |= AR71XX_SPI_IOC_DO;

	rb4xx_write(rbspi, AR71XX_SPI_REG_IOC, regval);
	rb4xx_write(rbspi, AR71XX_SPI_REG_IOC, regval | AR71XX_SPI_IOC_CLK);
}

static void do_spi_byte(struct rb4xx_spi *rbspi, u32 spi_ioc, u8 byte)
{
	int i;

	for (i = 7; i >= 0; i--)
		do_spi_clk(rbspi, spi_ioc, byte >> i);
}

/* The CS2 pin is used to clock in a second bit per clock cycle. */
static inline void do_spi_clk_two(struct rb4xx_spi *rbspi, u32 spi_ioc,
				   u8 value)
{
	u32 regval;

	regval = spi_ioc;
	if (value & BIT(1))
		regval |= AR71XX_SPI_IOC_DO;
	if (value & BIT(0))
		regval |= AR71XX_SPI_IOC_CS2;

	rb4xx_write(rbspi, AR71XX_SPI_REG_IOC, regval);
	rb4xx_write(rbspi, AR71XX_SPI_REG_IOC, regval | AR71XX_SPI_IOC_CLK);
}

/* Two bits at a time, msb first */
static void do_spi_byte_two(struct rb4xx_spi *rbspi, u32 spi_ioc, u8 byte)
{
	do_spi_clk_two(rbspi, spi_ioc, byte >> 6);
	do_spi_clk_two(rbspi, spi_ioc, byte >> 4);
	do_spi_clk_two(rbspi, spi_ioc, byte >> 2);
	do_spi_clk_two(rbspi, spi_ioc, byte >> 0);
}

static void rb4xx_set_cs(struct spi_device *spi, bool enable)
{
	struct rb4xx_spi *rbspi = spi_master_get_devdata(spi->master);

	/*
	 * Setting CS is done along with bitbanging the actual values,
	 * since it's all on the same hardware register. However the
	 * CPLD needs CS deselected after every command.
	 */
90
	if (enable)
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
		rb4xx_write(rbspi, AR71XX_SPI_REG_IOC,
			    AR71XX_SPI_IOC_CS0 | AR71XX_SPI_IOC_CS1);
}

static int rb4xx_transfer_one(struct spi_master *master,
			      struct spi_device *spi, struct spi_transfer *t)
{
	struct rb4xx_spi *rbspi = spi_master_get_devdata(master);
	int i;
	u32 spi_ioc;
	u8 *rx_buf;
	const u8 *tx_buf;

	/*
	 * Prime the SPI register with the SPI device selected. The m25p80 boot
	 * flash and CPLD share the CS0 pin. This works because the CPLD's
	 * command set was designed to almost not clash with that of the
	 * boot flash.
	 */
	if (spi->chip_select == 2)
		/* MMC */
		spi_ioc = AR71XX_SPI_IOC_CS0;
	else
		/* Boot flash and CPLD */
		spi_ioc = AR71XX_SPI_IOC_CS1;

	tx_buf = t->tx_buf;
	rx_buf = t->rx_buf;
	for (i = 0; i < t->len; ++i) {
		if (t->tx_nbits == SPI_NBITS_DUAL)
			/* CPLD can use two-wire transfers */
			do_spi_byte_two(rbspi, spi_ioc, tx_buf[i]);
		else
			do_spi_byte(rbspi, spi_ioc, tx_buf[i]);
		if (!rx_buf)
			continue;
		rx_buf[i] = rb4xx_read(rbspi, AR71XX_SPI_REG_RDS);
	}
	spi_finalize_current_transfer(master);

	return 0;
}

static int rb4xx_spi_probe(struct platform_device *pdev)
{
	struct spi_master *master;
	struct clk *ahb_clk;
	struct rb4xx_spi *rbspi;
	int err;
	void __iomem *spi_base;

142
	spi_base = devm_platform_ioremap_resource(pdev, 0);
143
	if (IS_ERR(spi_base))
144 145 146 147 148 149 150 151 152 153
		return PTR_ERR(spi_base);

	master = spi_alloc_master(&pdev->dev, sizeof(*rbspi));
	if (!master)
		return -ENOMEM;

	ahb_clk = devm_clk_get(&pdev->dev, "ahb");
	if (IS_ERR(ahb_clk))
		return PTR_ERR(ahb_clk);

154
	master->dev.of_node = pdev->dev.of_node;
155 156 157
	master->bus_num = 0;
	master->num_chipselect = 3;
	master->mode_bits = SPI_TX_DUAL;
158
	master->bits_per_word_mask = SPI_BPW_MASK(8);
159 160 161 162
	master->flags = SPI_MASTER_MUST_TX;
	master->transfer_one = rb4xx_transfer_one;
	master->set_cs = rb4xx_set_cs;

163 164 165 166 167
	rbspi = spi_master_get_devdata(master);
	rbspi->base = spi_base;
	rbspi->clk = ahb_clk;
	platform_set_drvdata(pdev, rbspi);

168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
	err = devm_spi_register_master(&pdev->dev, master);
	if (err) {
		dev_err(&pdev->dev, "failed to register SPI master\n");
		return err;
	}

	err = clk_prepare_enable(ahb_clk);
	if (err)
		return err;

	/* Enable SPI */
	rb4xx_write(rbspi, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO);

	return 0;
}

static int rb4xx_spi_remove(struct platform_device *pdev)
{
	struct rb4xx_spi *rbspi = platform_get_drvdata(pdev);

	clk_disable_unprepare(rbspi->clk);

	return 0;
}

193 194 195 196 197 198
static const struct of_device_id rb4xx_spi_dt_match[] = {
	{ .compatible = "mikrotik,rb4xx-spi" },
	{ },
};
MODULE_DEVICE_TABLE(of, rb4xx_spi_dt_match);

199 200 201 202 203
static struct platform_driver rb4xx_spi_drv = {
	.probe = rb4xx_spi_probe,
	.remove = rb4xx_spi_remove,
	.driver = {
		.name = "rb4xx-spi",
204
		.of_match_table = of_match_ptr(rb4xx_spi_dt_match),
205 206 207 208 209 210 211 212 213
	},
};

module_platform_driver(rb4xx_spi_drv);

MODULE_DESCRIPTION("Mikrotik RB4xx SPI controller driver");
MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
MODULE_AUTHOR("Bert Vermeulen <bert@biot.com>");
MODULE_LICENSE("GPL v2");