brintos

brintos / linux-shallow public Read only

0
0
Text · 5.6 KiB · 36f631e Raw
185 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Intel MAX 10 Board Management Controller chip4 *5 * Copyright (C) 2018-2020 Intel Corporation. All rights reserved.6 */7#include <linux/bitfield.h>8#include <linux/dev_printk.h>9#include <linux/init.h>10#include <linux/mfd/core.h>11#include <linux/mfd/intel-m10-bmc.h>12#include <linux/module.h>13#include <linux/regmap.h>14#include <linux/spi/spi.h>15 16static const struct regmap_range m10bmc_regmap_range[] = {17	regmap_reg_range(M10BMC_N3000_LEGACY_BUILD_VER, M10BMC_N3000_LEGACY_BUILD_VER),18	regmap_reg_range(M10BMC_N3000_SYS_BASE, M10BMC_N3000_SYS_END),19	regmap_reg_range(M10BMC_N3000_FLASH_BASE, M10BMC_N3000_FLASH_END),20};21 22static const struct regmap_access_table m10bmc_access_table = {23	.yes_ranges	= m10bmc_regmap_range,24	.n_yes_ranges	= ARRAY_SIZE(m10bmc_regmap_range),25};26 27static const struct regmap_config intel_m10bmc_regmap_config = {28	.reg_bits = 32,29	.val_bits = 32,30	.reg_stride = 4,31	.wr_table = &m10bmc_access_table,32	.rd_table = &m10bmc_access_table,33	.max_register = M10BMC_N3000_MEM_END,34};35 36static int check_m10bmc_version(struct intel_m10bmc *ddata)37{38	unsigned int v;39	int ret;40 41	/*42	 * This check is to filter out the very old legacy BMC versions. In the43	 * old BMC chips, the BMC version info is stored in the old version44	 * register (M10BMC_N3000_LEGACY_BUILD_VER), so its read out value would have45	 * not been M10BMC_N3000_VER_LEGACY_INVALID (0xffffffff). But in new BMC46	 * chips that the driver supports, the value of this register should be47	 * M10BMC_N3000_VER_LEGACY_INVALID.48	 */49	ret = m10bmc_raw_read(ddata, M10BMC_N3000_LEGACY_BUILD_VER, &v);50	if (ret)51		return -ENODEV;52 53	if (v != M10BMC_N3000_VER_LEGACY_INVALID) {54		dev_err(ddata->dev, "bad version M10BMC detected\n");55		return -ENODEV;56	}57 58	return 0;59}60 61static int intel_m10_bmc_spi_probe(struct spi_device *spi)62{63	const struct spi_device_id *id = spi_get_device_id(spi);64	const struct intel_m10bmc_platform_info *info;65	struct device *dev = &spi->dev;66	struct intel_m10bmc *ddata;67	int ret;68 69	ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);70	if (!ddata)71		return -ENOMEM;72 73	info = (struct intel_m10bmc_platform_info *)id->driver_data;74	ddata->dev = dev;75 76	ddata->regmap = devm_regmap_init_spi_avmm(spi, &intel_m10bmc_regmap_config);77	if (IS_ERR(ddata->regmap)) {78		ret = PTR_ERR(ddata->regmap);79		dev_err(dev, "Failed to allocate regmap: %d\n", ret);80		return ret;81	}82 83	spi_set_drvdata(spi, ddata);84 85	ret = check_m10bmc_version(ddata);86	if (ret) {87		dev_err(dev, "Failed to identify m10bmc hardware\n");88		return ret;89	}90 91	return m10bmc_dev_init(ddata, info);92}93 94static const struct m10bmc_csr_map m10bmc_n3000_csr_map = {95	.base = M10BMC_N3000_SYS_BASE,96	.build_version = M10BMC_N3000_BUILD_VER,97	.fw_version = NIOS2_N3000_FW_VERSION,98	.mac_low = M10BMC_N3000_MAC_LOW,99	.mac_high = M10BMC_N3000_MAC_HIGH,100	.doorbell = M10BMC_N3000_DOORBELL,101	.auth_result = M10BMC_N3000_AUTH_RESULT,102	.bmc_prog_addr = M10BMC_N3000_BMC_PROG_ADDR,103	.bmc_reh_addr = M10BMC_N3000_BMC_REH_ADDR,104	.bmc_magic = M10BMC_N3000_BMC_PROG_MAGIC,105	.sr_prog_addr = M10BMC_N3000_SR_PROG_ADDR,106	.sr_reh_addr = M10BMC_N3000_SR_REH_ADDR,107	.sr_magic = M10BMC_N3000_SR_PROG_MAGIC,108	.pr_prog_addr = M10BMC_N3000_PR_PROG_ADDR,109	.pr_reh_addr = M10BMC_N3000_PR_REH_ADDR,110	.pr_magic = M10BMC_N3000_PR_PROG_MAGIC,111	.rsu_update_counter = M10BMC_N3000_STAGING_FLASH_COUNT,112	.staging_size = M10BMC_STAGING_SIZE,113};114 115static struct mfd_cell m10bmc_d5005_subdevs[] = {116	{ .name = "d5005bmc-hwmon" },117	{ .name = "d5005bmc-sec-update" },118};119 120static const struct regmap_range m10bmc_d5005_fw_handshake_regs[] = {121	regmap_reg_range(M10BMC_N3000_TELEM_START, M10BMC_D5005_TELEM_END),122};123 124static struct mfd_cell m10bmc_pacn3000_subdevs[] = {125	{ .name = "n3000bmc-hwmon" },126	{ .name = "n3000bmc-retimer" },127	{ .name = "n3000bmc-sec-update" },128};129 130static const struct regmap_range m10bmc_n3000_fw_handshake_regs[] = {131	regmap_reg_range(M10BMC_N3000_TELEM_START, M10BMC_N3000_TELEM_END),132};133 134static struct mfd_cell m10bmc_n5010_subdevs[] = {135	{ .name = "n5010bmc-hwmon" },136};137 138static const struct intel_m10bmc_platform_info m10bmc_spi_n3000 = {139	.cells = m10bmc_pacn3000_subdevs,140	.n_cells = ARRAY_SIZE(m10bmc_pacn3000_subdevs),141	.handshake_sys_reg_ranges = m10bmc_n3000_fw_handshake_regs,142	.handshake_sys_reg_nranges = ARRAY_SIZE(m10bmc_n3000_fw_handshake_regs),143	.csr_map = &m10bmc_n3000_csr_map,144};145 146static const struct intel_m10bmc_platform_info m10bmc_spi_d5005 = {147	.cells = m10bmc_d5005_subdevs,148	.n_cells = ARRAY_SIZE(m10bmc_d5005_subdevs),149	.handshake_sys_reg_ranges = m10bmc_d5005_fw_handshake_regs,150	.handshake_sys_reg_nranges = ARRAY_SIZE(m10bmc_d5005_fw_handshake_regs),151	.csr_map = &m10bmc_n3000_csr_map,152};153 154static const struct intel_m10bmc_platform_info m10bmc_spi_n5010 = {155	.cells = m10bmc_n5010_subdevs,156	.n_cells = ARRAY_SIZE(m10bmc_n5010_subdevs),157	.handshake_sys_reg_ranges = m10bmc_n3000_fw_handshake_regs,158	.handshake_sys_reg_nranges = ARRAY_SIZE(m10bmc_n3000_fw_handshake_regs),159	.csr_map = &m10bmc_n3000_csr_map,160};161 162static const struct spi_device_id m10bmc_spi_id[] = {163	{ "m10-n3000", (kernel_ulong_t)&m10bmc_spi_n3000 },164	{ "m10-d5005", (kernel_ulong_t)&m10bmc_spi_d5005 },165	{ "m10-n5010", (kernel_ulong_t)&m10bmc_spi_n5010 },166	{ }167};168MODULE_DEVICE_TABLE(spi, m10bmc_spi_id);169 170static struct spi_driver intel_m10bmc_spi_driver = {171	.driver = {172		.name = "intel-m10-bmc",173		.dev_groups = m10bmc_dev_groups,174	},175	.probe = intel_m10_bmc_spi_probe,176	.id_table = m10bmc_spi_id,177};178module_spi_driver(intel_m10bmc_spi_driver);179 180MODULE_DESCRIPTION("Intel MAX 10 BMC SPI bus interface");181MODULE_AUTHOR("Intel Corporation");182MODULE_LICENSE("GPL v2");183MODULE_ALIAS("spi:intel-m10-bmc");184MODULE_IMPORT_NS(INTEL_M10_BMC_CORE);185