brintos

brintos / linux-shallow public Read only

0
0
Text · 3.5 KiB · ba981a7 Raw
144 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Driver for Khadas System control Microcontroller4 *5 * Copyright (C) 2020 BayLibre SAS6 *7 * Author(s): Neil Armstrong <narmstrong@baylibre.com>8 */9#include <linux/bitfield.h>10#include <linux/i2c.h>11#include <linux/mfd/core.h>12#include <linux/mfd/khadas-mcu.h>13#include <linux/module.h>14#include <linux/regmap.h>15 16static bool khadas_mcu_reg_volatile(struct device *dev, unsigned int reg)17{18	if (reg >= KHADAS_MCU_USER_DATA_0_REG &&19	    reg < KHADAS_MCU_PWR_OFF_CMD_REG)20		return true;21 22	switch (reg) {23	case KHADAS_MCU_PWR_OFF_CMD_REG:24	case KHADAS_MCU_PASSWD_START_REG:25	case KHADAS_MCU_CHECK_VEN_PASSWD_REG:26	case KHADAS_MCU_CHECK_USER_PASSWD_REG:27	case KHADAS_MCU_WOL_INIT_START_REG:28	case KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG:29		return true;30	default:31		return false;32	}33}34 35static bool khadas_mcu_reg_writeable(struct device *dev, unsigned int reg)36{37	switch (reg) {38	case KHADAS_MCU_PASSWD_VEN_0_REG:39	case KHADAS_MCU_PASSWD_VEN_1_REG:40	case KHADAS_MCU_PASSWD_VEN_2_REG:41	case KHADAS_MCU_PASSWD_VEN_3_REG:42	case KHADAS_MCU_PASSWD_VEN_4_REG:43	case KHADAS_MCU_PASSWD_VEN_5_REG:44	case KHADAS_MCU_MAC_0_REG:45	case KHADAS_MCU_MAC_1_REG:46	case KHADAS_MCU_MAC_2_REG:47	case KHADAS_MCU_MAC_3_REG:48	case KHADAS_MCU_MAC_4_REG:49	case KHADAS_MCU_MAC_5_REG:50	case KHADAS_MCU_USID_0_REG:51	case KHADAS_MCU_USID_1_REG:52	case KHADAS_MCU_USID_2_REG:53	case KHADAS_MCU_USID_3_REG:54	case KHADAS_MCU_USID_4_REG:55	case KHADAS_MCU_USID_5_REG:56	case KHADAS_MCU_VERSION_0_REG:57	case KHADAS_MCU_VERSION_1_REG:58	case KHADAS_MCU_DEVICE_NO_0_REG:59	case KHADAS_MCU_DEVICE_NO_1_REG:60	case KHADAS_MCU_FACTORY_TEST_REG:61	case KHADAS_MCU_SHUTDOWN_NORMAL_STATUS_REG:62		return false;63	default:64		return true;65	}66}67 68static const struct regmap_config khadas_mcu_regmap_config = {69	.reg_bits	= 8,70	.reg_stride	= 1,71	.val_bits	= 8,72	.max_register	= KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,73	.volatile_reg	= khadas_mcu_reg_volatile,74	.writeable_reg	= khadas_mcu_reg_writeable,75	.cache_type	= REGCACHE_MAPLE,76};77 78static struct mfd_cell khadas_mcu_fan_cells[] = {79	/* VIM1/2 Rev13+ and VIM3 only */80	{ .name = "khadas-mcu-fan-ctrl", },81};82 83static struct mfd_cell khadas_mcu_cells[] = {84	{ .name = "khadas-mcu-user-mem", },85};86 87static int khadas_mcu_probe(struct i2c_client *client)88{89	struct device *dev = &client->dev;90	struct khadas_mcu *ddata;91	int ret;92 93	ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);94	if (!ddata)95		return -ENOMEM;96 97	i2c_set_clientdata(client, ddata);98 99	ddata->dev = dev;100 101	ddata->regmap = devm_regmap_init_i2c(client, &khadas_mcu_regmap_config);102	if (IS_ERR(ddata->regmap)) {103		ret = PTR_ERR(ddata->regmap);104		dev_err(dev, "Failed to allocate register map: %d\n", ret);105		return ret;106	}107 108	ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,109				   khadas_mcu_cells,110				   ARRAY_SIZE(khadas_mcu_cells),111				   NULL, 0, NULL);112	if (ret)113		return ret;114 115	if (of_property_present(dev->of_node, "#cooling-cells"))116		return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,117					    khadas_mcu_fan_cells,118					    ARRAY_SIZE(khadas_mcu_fan_cells),119					    NULL, 0, NULL);120 121	return 0;122}123 124#ifdef CONFIG_OF125static const struct of_device_id khadas_mcu_of_match[] = {126	{ .compatible = "khadas,mcu", },127	{},128};129MODULE_DEVICE_TABLE(of, khadas_mcu_of_match);130#endif131 132static struct i2c_driver khadas_mcu_driver = {133	.driver = {134		.name = "khadas-mcu-core",135		.of_match_table = of_match_ptr(khadas_mcu_of_match),136	},137	.probe = khadas_mcu_probe,138};139module_i2c_driver(khadas_mcu_driver);140 141MODULE_DESCRIPTION("Khadas MCU core driver");142MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");143MODULE_LICENSE("GPL v2");144