2020-09-15 11:44:21 +08:00
// SPDX-License-Identifier: GPL-2.0
/*
* Intel MAX 10 Board Management Controller chip
*
* Copyright ( C ) 2018 - 2020 Intel Corporation . All rights reserved .
*/
# include <linux/bitfield.h>
2023-01-16 12:08:38 +02:00
# include <linux/dev_printk.h>
2020-09-15 11:44:21 +08:00
# include <linux/init.h>
# include <linux/mfd/core.h>
# include <linux/mfd/intel-m10-bmc.h>
# include <linux/module.h>
# include <linux/regmap.h>
# include <linux/spi/spi.h>
2021-03-10 23:55:47 +08:00
static const struct regmap_range m10bmc_regmap_range [ ] = {
2023-01-16 12:08:41 +02:00
regmap_reg_range ( M10BMC_N3000_LEGACY_BUILD_VER , M10BMC_N3000_LEGACY_BUILD_VER ) ,
regmap_reg_range ( M10BMC_N3000_SYS_BASE , M10BMC_N3000_SYS_END ) ,
regmap_reg_range ( M10BMC_N3000_FLASH_BASE , M10BMC_N3000_FLASH_END ) ,
2021-03-10 23:55:47 +08:00
} ;
static const struct regmap_access_table m10bmc_access_table = {
. yes_ranges = m10bmc_regmap_range ,
. n_yes_ranges = ARRAY_SIZE ( m10bmc_regmap_range ) ,
} ;
2020-09-15 11:44:21 +08:00
static struct regmap_config intel_m10bmc_regmap_config = {
. reg_bits = 32 ,
. val_bits = 32 ,
. reg_stride = 4 ,
2021-03-10 23:55:47 +08:00
. wr_table = & m10bmc_access_table ,
. rd_table = & m10bmc_access_table ,
2023-01-16 12:08:41 +02:00
. max_register = M10BMC_N3000_MEM_END ,
2020-09-15 11:44:21 +08:00
} ;
static int check_m10bmc_version ( struct intel_m10bmc * ddata )
{
unsigned int v ;
int ret ;
/*
2021-03-10 23:55:46 +08:00
* This check is to filter out the very old legacy BMC versions . In the
* old BMC chips , the BMC version info is stored in the old version
2023-01-16 12:08:41 +02:00
* register ( M10BMC_N3000_LEGACY_BUILD_VER ) , so its read out value would have
* not been M10BMC_N3000_VER_LEGACY_INVALID ( 0xffffffff ) . But in new BMC
2021-03-10 23:55:46 +08:00
* chips that the driver supports , the value of this register should be
2023-01-16 12:08:41 +02:00
* M10BMC_N3000_VER_LEGACY_INVALID .
2020-09-15 11:44:21 +08:00
*/
2023-01-16 12:08:41 +02:00
ret = m10bmc_raw_read ( ddata , M10BMC_N3000_LEGACY_BUILD_VER , & v ) ;
2020-09-15 11:44:21 +08:00
if ( ret )
return - ENODEV ;
2023-01-16 12:08:41 +02:00
if ( v ! = M10BMC_N3000_VER_LEGACY_INVALID ) {
2020-09-15 11:44:21 +08:00
dev_err ( ddata - > dev , " bad version M10BMC detected \n " ) ;
return - ENODEV ;
}
return 0 ;
}
static int intel_m10_bmc_spi_probe ( struct spi_device * spi )
{
const struct spi_device_id * id = spi_get_device_id ( spi ) ;
2023-01-16 12:08:36 +02:00
const struct intel_m10bmc_platform_info * info ;
2020-09-15 11:44:21 +08:00
struct device * dev = & spi - > dev ;
struct intel_m10bmc * ddata ;
2023-01-16 12:08:36 +02:00
int ret ;
2020-09-15 11:44:21 +08:00
ddata = devm_kzalloc ( dev , sizeof ( * ddata ) , GFP_KERNEL ) ;
if ( ! ddata )
return - ENOMEM ;
2023-01-16 12:08:36 +02:00
info = ( struct intel_m10bmc_platform_info * ) id - > driver_data ;
2020-09-15 11:44:21 +08:00
ddata - > dev = dev ;
2023-01-16 12:08:38 +02:00
ddata - > regmap = devm_regmap_init_spi_avmm ( spi , & intel_m10bmc_regmap_config ) ;
2020-09-15 11:44:21 +08:00
if ( IS_ERR ( ddata - > regmap ) ) {
ret = PTR_ERR ( ddata - > regmap ) ;
dev_err ( dev , " Failed to allocate regmap: %d \n " , ret ) ;
return ret ;
}
spi_set_drvdata ( spi , ddata ) ;
ret = check_m10bmc_version ( ddata ) ;
if ( ret ) {
dev_err ( dev , " Failed to identify m10bmc hardware \n " ) ;
return ret ;
}
2023-01-16 12:08:38 +02:00
return m10bmc_dev_init ( ddata , info ) ;
2020-09-15 11:44:21 +08:00
}
2023-01-16 12:08:39 +02:00
static const struct m10bmc_csr_map m10bmc_n3000_csr_map = {
2023-01-16 12:08:41 +02:00
. base = M10BMC_N3000_SYS_BASE ,
. build_version = M10BMC_N3000_BUILD_VER ,
. fw_version = NIOS2_N3000_FW_VERSION ,
. mac_low = M10BMC_N3000_MAC_LOW ,
. mac_high = M10BMC_N3000_MAC_HIGH ,
. doorbell = M10BMC_N3000_DOORBELL ,
. auth_result = M10BMC_N3000_AUTH_RESULT ,
. bmc_prog_addr = M10BMC_N3000_BMC_PROG_ADDR ,
. bmc_reh_addr = M10BMC_N3000_BMC_REH_ADDR ,
. bmc_magic = M10BMC_N3000_BMC_PROG_MAGIC ,
. sr_prog_addr = M10BMC_N3000_SR_PROG_ADDR ,
. sr_reh_addr = M10BMC_N3000_SR_REH_ADDR ,
. sr_magic = M10BMC_N3000_SR_PROG_MAGIC ,
. pr_prog_addr = M10BMC_N3000_PR_PROG_ADDR ,
. pr_reh_addr = M10BMC_N3000_PR_REH_ADDR ,
. pr_magic = M10BMC_N3000_PR_PROG_MAGIC ,
. rsu_update_counter = M10BMC_N3000_STAGING_FLASH_COUNT ,
2023-01-16 12:08:39 +02:00
} ;
2023-01-16 12:08:38 +02:00
static struct mfd_cell m10bmc_d5005_subdevs [ ] = {
{ . name = " d5005bmc-hwmon " } ,
{ . name = " d5005bmc-sec-update " } ,
} ;
2023-04-17 12:26:53 +03:00
static const struct regmap_range m10bmc_d5005_fw_handshake_regs [ ] = {
regmap_reg_range ( M10BMC_N3000_TELEM_START , M10BMC_D5005_TELEM_END ) ,
} ;
2023-01-16 12:08:38 +02:00
static struct mfd_cell m10bmc_pacn3000_subdevs [ ] = {
{ . name = " n3000bmc-hwmon " } ,
{ . name = " n3000bmc-retimer " } ,
{ . name = " n3000bmc-sec-update " } ,
} ;
2023-04-17 12:26:53 +03:00
static const struct regmap_range m10bmc_n3000_fw_handshake_regs [ ] = {
regmap_reg_range ( M10BMC_N3000_TELEM_START , M10BMC_N3000_TELEM_END ) ,
} ;
2023-01-16 12:08:38 +02:00
static struct mfd_cell m10bmc_n5010_subdevs [ ] = {
{ . name = " n5010bmc-hwmon " } ,
} ;
2023-01-16 12:08:36 +02:00
static const struct intel_m10bmc_platform_info m10bmc_spi_n3000 = {
. cells = m10bmc_pacn3000_subdevs ,
. n_cells = ARRAY_SIZE ( m10bmc_pacn3000_subdevs ) ,
2023-04-17 12:26:53 +03:00
. handshake_sys_reg_ranges = m10bmc_n3000_fw_handshake_regs ,
. handshake_sys_reg_nranges = ARRAY_SIZE ( m10bmc_n3000_fw_handshake_regs ) ,
2023-01-16 12:08:39 +02:00
. csr_map = & m10bmc_n3000_csr_map ,
2023-01-16 12:08:36 +02:00
} ;
static const struct intel_m10bmc_platform_info m10bmc_spi_d5005 = {
. cells = m10bmc_d5005_subdevs ,
. n_cells = ARRAY_SIZE ( m10bmc_d5005_subdevs ) ,
2023-04-17 12:26:53 +03:00
. handshake_sys_reg_ranges = m10bmc_d5005_fw_handshake_regs ,
. handshake_sys_reg_nranges = ARRAY_SIZE ( m10bmc_d5005_fw_handshake_regs ) ,
2023-01-16 12:08:39 +02:00
. csr_map = & m10bmc_n3000_csr_map ,
2023-01-16 12:08:36 +02:00
} ;
static const struct intel_m10bmc_platform_info m10bmc_spi_n5010 = {
. cells = m10bmc_n5010_subdevs ,
. n_cells = ARRAY_SIZE ( m10bmc_n5010_subdevs ) ,
2023-04-17 12:26:53 +03:00
. handshake_sys_reg_ranges = m10bmc_n3000_fw_handshake_regs ,
. handshake_sys_reg_nranges = ARRAY_SIZE ( m10bmc_n3000_fw_handshake_regs ) ,
2023-01-16 12:08:39 +02:00
. csr_map = & m10bmc_n3000_csr_map ,
2023-01-16 12:08:36 +02:00
} ;
2020-09-15 11:44:21 +08:00
static const struct spi_device_id m10bmc_spi_id [ ] = {
2023-01-16 12:08:36 +02:00
{ " m10-n3000 " , ( kernel_ulong_t ) & m10bmc_spi_n3000 } ,
{ " m10-d5005 " , ( kernel_ulong_t ) & m10bmc_spi_d5005 } ,
{ " m10-n5010 " , ( kernel_ulong_t ) & m10bmc_spi_n5010 } ,
2020-09-15 11:44:21 +08:00
{ }
} ;
MODULE_DEVICE_TABLE ( spi , m10bmc_spi_id ) ;
static struct spi_driver intel_m10bmc_spi_driver = {
. driver = {
. name = " intel-m10-bmc " ,
2023-01-16 12:08:38 +02:00
. dev_groups = m10bmc_dev_groups ,
2020-09-15 11:44:21 +08:00
} ,
. probe = intel_m10_bmc_spi_probe ,
. id_table = m10bmc_spi_id ,
} ;
module_spi_driver ( intel_m10bmc_spi_driver ) ;
2023-01-16 12:08:38 +02:00
MODULE_DESCRIPTION ( " Intel MAX 10 BMC SPI bus interface " ) ;
2020-09-15 11:44:21 +08:00
MODULE_AUTHOR ( " Intel Corporation " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_ALIAS ( " spi:intel-m10-bmc " ) ;
2023-04-17 12:26:50 +03:00
MODULE_IMPORT_NS ( INTEL_M10_BMC_CORE ) ;