brintos

brintos / linux-shallow public Read only

0
0
Text · 3.4 KiB · 3405fb8 Raw
125 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Rockchip RK806 Core (SPI) driver4 *5 * Copyright (c) 2021 Rockchip Electronics Co., Ltd.6 * Copyright (c) 2023 Collabora Ltd.7 *8 * Author: Xu Shengfei <xsf@rock-chips.com>9 * Author: Sebastian Reichel <sebastian.reichel@collabora.com>10 */11 12#include <linux/interrupt.h>13#include <linux/mfd/core.h>14#include <linux/mfd/rk808.h>15#include <linux/module.h>16#include <linux/regmap.h>17#include <linux/spi/spi.h>18 19#define RK806_ADDR_SIZE 220#define RK806_CMD_WITH_SIZE(CMD, VALUE_BYTES) \21	(RK806_CMD_##CMD | RK806_CMD_CRC_DIS | (VALUE_BYTES - 1))22 23static const struct regmap_range rk806_volatile_ranges[] = {24	regmap_reg_range(RK806_POWER_EN0, RK806_POWER_EN5),25	regmap_reg_range(RK806_DVS_START_CTRL, RK806_INT_MSK1),26};27 28static const struct regmap_access_table rk806_volatile_table = {29	.yes_ranges = rk806_volatile_ranges,30	.n_yes_ranges = ARRAY_SIZE(rk806_volatile_ranges),31};32 33static const struct regmap_config rk806_regmap_config_spi = {34	.reg_bits = 16,35	.val_bits = 8,36	.max_register = RK806_BUCK_RSERVE_REG5,37	.cache_type = REGCACHE_MAPLE,38	.volatile_table = &rk806_volatile_table,39};40 41static int rk806_spi_bus_write(void *context, const void *vdata, size_t count)42{43	struct device *dev = context;44	struct spi_device *spi = to_spi_device(dev);45	struct spi_transfer xfer[2] = { 0 };46	/* data and thus count includes the register address */47	size_t val_size = count - RK806_ADDR_SIZE;48	char cmd;49 50	if (val_size < 1 || val_size > (RK806_CMD_LEN_MSK + 1))51		return -EINVAL;52 53	cmd = RK806_CMD_WITH_SIZE(WRITE, val_size);54 55	xfer[0].tx_buf = &cmd;56	xfer[0].len = sizeof(cmd);57	xfer[1].tx_buf = vdata;58	xfer[1].len = count;59 60	return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));61}62 63static int rk806_spi_bus_read(void *context, const void *vreg, size_t reg_size,64			      void *val, size_t val_size)65{66	struct device *dev = context;67	struct spi_device *spi = to_spi_device(dev);68	char txbuf[3] = { 0 };69 70	if (reg_size != RK806_ADDR_SIZE ||71	    val_size < 1 || val_size > (RK806_CMD_LEN_MSK + 1))72		return -EINVAL;73 74	/* TX buffer contains command byte followed by two address bytes */75	txbuf[0] = RK806_CMD_WITH_SIZE(READ, val_size);76	memcpy(txbuf+1, vreg, reg_size);77 78	return spi_write_then_read(spi, txbuf, sizeof(txbuf), val, val_size);79}80 81static const struct regmap_bus rk806_regmap_bus_spi = {82	.write = rk806_spi_bus_write,83	.read = rk806_spi_bus_read,84	.reg_format_endian_default = REGMAP_ENDIAN_LITTLE,85};86 87static int rk8xx_spi_probe(struct spi_device *spi)88{89	struct regmap *regmap;90 91	regmap = devm_regmap_init(&spi->dev, &rk806_regmap_bus_spi,92				  &spi->dev, &rk806_regmap_config_spi);93	if (IS_ERR(regmap))94		return dev_err_probe(&spi->dev, PTR_ERR(regmap),95				     "Failed to init regmap\n");96 97	return rk8xx_probe(&spi->dev, RK806_ID, spi->irq, regmap);98}99 100static const struct of_device_id rk8xx_spi_of_match[] = {101	{ .compatible = "rockchip,rk806", },102	{ }103};104MODULE_DEVICE_TABLE(of, rk8xx_spi_of_match);105 106static const struct spi_device_id rk8xx_spi_id_table[] = {107	{ "rk806", 0 },108	{ }109};110MODULE_DEVICE_TABLE(spi, rk8xx_spi_id_table);111 112static struct spi_driver rk8xx_spi_driver = {113	.driver		= {114		.name	= "rk8xx-spi",115		.of_match_table = rk8xx_spi_of_match,116	},117	.probe		= rk8xx_spi_probe,118	.id_table	= rk8xx_spi_id_table,119};120module_spi_driver(rk8xx_spi_driver);121 122MODULE_AUTHOR("Xu Shengfei <xsf@rock-chips.com>");123MODULE_DESCRIPTION("RK8xx SPI PMIC driver");124MODULE_LICENSE("GPL");125