brintos

brintos / linux-shallow public Read only

0
0
Text · 4.6 KiB · 0b0123e Raw
210 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2 3#include <linux/module.h>4#include <linux/platform_device.h>5#include <linux/mod_devicetable.h>6#include <linux/spi/spi.h>7 8struct rtspi {9	void __iomem *base;10};11 12/* SPI Flash Configuration Register */13#define RTL_SPI_SFCR			0x0014#define RTL_SPI_SFCR_RBO		BIT(28)15#define RTL_SPI_SFCR_WBO		BIT(27)16 17/* SPI Flash Control and Status Register */18#define RTL_SPI_SFCSR			0x0819#define RTL_SPI_SFCSR_CSB0		BIT(31)20#define RTL_SPI_SFCSR_CSB1		BIT(30)21#define RTL_SPI_SFCSR_RDY		BIT(27)22#define RTL_SPI_SFCSR_CS		BIT(24)23#define RTL_SPI_SFCSR_LEN_MASK		~(0x03 << 28)24#define RTL_SPI_SFCSR_LEN1		(0x00 << 28)25#define RTL_SPI_SFCSR_LEN4		(0x03 << 28)26 27/* SPI Flash Data Register */28#define RTL_SPI_SFDR			0x0c29 30#define REG(x)		(rtspi->base + x)31 32 33static void rt_set_cs(struct spi_device *spi, bool active)34{35	struct rtspi *rtspi = spi_controller_get_devdata(spi->controller);36	u32 value;37 38	/* CS0 bit is active low */39	value = readl(REG(RTL_SPI_SFCSR));40	if (active)41		value |= RTL_SPI_SFCSR_CSB0;42	else43		value &= ~RTL_SPI_SFCSR_CSB0;44	writel(value, REG(RTL_SPI_SFCSR));45}46 47static void set_size(struct rtspi *rtspi, int size)48{49	u32 value;50 51	value = readl(REG(RTL_SPI_SFCSR));52	value &= RTL_SPI_SFCSR_LEN_MASK;53	if (size == 4)54		value |= RTL_SPI_SFCSR_LEN4;55	else if (size == 1)56		value |= RTL_SPI_SFCSR_LEN1;57	writel(value, REG(RTL_SPI_SFCSR));58}59 60static inline void wait_ready(struct rtspi *rtspi)61{62	while (!(readl(REG(RTL_SPI_SFCSR)) & RTL_SPI_SFCSR_RDY))63		cpu_relax();64}65static void send4(struct rtspi *rtspi, const u32 *buf)66{67	wait_ready(rtspi);68	set_size(rtspi, 4);69	writel(*buf, REG(RTL_SPI_SFDR));70}71 72static void send1(struct rtspi *rtspi, const u8 *buf)73{74	wait_ready(rtspi);75	set_size(rtspi, 1);76	writel(buf[0] << 24, REG(RTL_SPI_SFDR));77}78 79static void rcv4(struct rtspi *rtspi, u32 *buf)80{81	wait_ready(rtspi);82	set_size(rtspi, 4);83	*buf = readl(REG(RTL_SPI_SFDR));84}85 86static void rcv1(struct rtspi *rtspi, u8 *buf)87{88	wait_ready(rtspi);89	set_size(rtspi, 1);90	*buf = readl(REG(RTL_SPI_SFDR)) >> 24;91}92 93static int transfer_one(struct spi_controller *ctrl, struct spi_device *spi,94			struct spi_transfer *xfer)95{96	struct rtspi *rtspi = spi_controller_get_devdata(ctrl);97	void *rx_buf;98	const void *tx_buf;99	int cnt;100 101	tx_buf = xfer->tx_buf;102	rx_buf = xfer->rx_buf;103	cnt = xfer->len;104	if (tx_buf) {105		while (cnt >= 4) {106			send4(rtspi, tx_buf);107			tx_buf += 4;108			cnt -= 4;109		}110		while (cnt) {111			send1(rtspi, tx_buf);112			tx_buf++;113			cnt--;114		}115	} else if (rx_buf) {116		while (cnt >= 4) {117			rcv4(rtspi, rx_buf);118			rx_buf += 4;119			cnt -= 4;120		}121		while (cnt) {122			rcv1(rtspi, rx_buf);123			rx_buf++;124			cnt--;125		}126	}127 128	spi_finalize_current_transfer(ctrl);129 130	return 0;131}132 133static void init_hw(struct rtspi *rtspi)134{135	u32 value;136 137	/* Turn on big-endian byte ordering */138	value = readl(REG(RTL_SPI_SFCR));139	value |= RTL_SPI_SFCR_RBO | RTL_SPI_SFCR_WBO;140	writel(value, REG(RTL_SPI_SFCR));141 142	value = readl(REG(RTL_SPI_SFCSR));143	/* Permanently disable CS1, since it's never used */144	value |= RTL_SPI_SFCSR_CSB1;145	/* Select CS0 for use */146	value &= RTL_SPI_SFCSR_CS;147	writel(value, REG(RTL_SPI_SFCSR));148}149 150static int realtek_rtl_spi_probe(struct platform_device *pdev)151{152	struct spi_controller *ctrl;153	struct rtspi *rtspi;154	int err;155 156	ctrl = devm_spi_alloc_host(&pdev->dev, sizeof(*rtspi));157	if (!ctrl) {158		dev_err(&pdev->dev, "Error allocating SPI controller\n");159		return -ENOMEM;160	}161	platform_set_drvdata(pdev, ctrl);162	rtspi = spi_controller_get_devdata(ctrl);163 164	rtspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);165	if (IS_ERR(rtspi->base)) {166		dev_err(&pdev->dev, "Could not map SPI register address");167		return -ENOMEM;168	}169 170	init_hw(rtspi);171 172	ctrl->dev.of_node = pdev->dev.of_node;173	ctrl->flags = SPI_CONTROLLER_HALF_DUPLEX;174	ctrl->set_cs = rt_set_cs;175	ctrl->transfer_one = transfer_one;176 177	err = devm_spi_register_controller(&pdev->dev, ctrl);178	if (err) {179		dev_err(&pdev->dev, "Could not register SPI controller\n");180		return -ENODEV;181	}182 183	return 0;184}185 186 187static const struct of_device_id realtek_rtl_spi_of_ids[] = {188	{ .compatible = "realtek,rtl8380-spi" },189	{ .compatible = "realtek,rtl8382-spi" },190	{ .compatible = "realtek,rtl8391-spi" },191	{ .compatible = "realtek,rtl8392-spi" },192	{ .compatible = "realtek,rtl8393-spi" },193	{ /* sentinel */ }194};195MODULE_DEVICE_TABLE(of, realtek_rtl_spi_of_ids);196 197static struct platform_driver realtek_rtl_spi_driver = {198	.probe = realtek_rtl_spi_probe,199	.driver = {200		.name = "realtek-rtl-spi",201		.of_match_table = realtek_rtl_spi_of_ids,202	},203};204 205module_platform_driver(realtek_rtl_spi_driver);206 207MODULE_LICENSE("GPL v2");208MODULE_AUTHOR("Bert Vermeulen <bert@biot.com>");209MODULE_DESCRIPTION("Realtek RTL SPI driver");210