// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) KEBA Industrial Automation Gmbh 2024
*
* Driver for KEBA system FPGA
*
* The KEBA system FPGA implements various devices. This driver registers
* auxiliary devices for every device within the FPGA.
*/
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/misc/keba.h>
#include <linux/module.h>
#include <linux/mtd/partitions.h>
#include <linux/nvmem-consumer.h>
#include <linux/nvmem-provider.h>
#include <linux/pci.h>
#include <linux/spi/flash.h>
#include <linux/spi/spi.h>
#define CP500 "cp500"
#define PCI_VENDOR_ID_KEBA 0xCEBA
#define PCI_DEVICE_ID_KEBA_CP035 0x2706
#define PCI_DEVICE_ID_KEBA_CP505 0x2703
#define PCI_DEVICE_ID_KEBA_CP520 0x2696
#define CP500_SYS_BAR 0
#define CP500_ECM_BAR 1
/* BAR 0 registers */
#define CP500_VERSION_REG 0x00
#define CP500_RECONFIG_REG 0x11 /* upper 8-bits of STARTUP register */
#define CP500_PRESENT_REG 0x20
#define CP500_AXI_REG 0x40
/* Bits in BUILD_REG */
#define CP500_BUILD_TEST 0x8000 /* FPGA test version */
/* Bits in RECONFIG_REG */
#define CP500_RECFG_REQ 0x01 /* reconfigure FPGA on next reset */
/* Bits in PRESENT_REG */
#define CP500_PRESENT_FAN0 0x01
/* MSIX */
#define CP500_AXI_MSIX 3
#define CP500_RFB_UART_MSIX 4
#define CP500_DEBUG_UART_MSIX 5
#define CP500_SI1_UART_MSIX 6
#define CP500_NUM_MSIX 8
#define CP500_NUM_MSIX_NO_MMI 2
#define CP500_NUM_MSIX_NO_AXI 3
/* EEPROM */
#define CP500_EEPROM_DA_OFFSET 0x016F
#define CP500_EEPROM_DA_ESC_TYPE_MASK 0x01
#define CP500_EEPROM_ESC_LAN9252 0x00
#define CP500_EEPROM_ESC_ET1100 0x01
#define CP500_EEPROM_CPU_NAME "cpu_eeprom"
#define CP500_EEPROM_CPU_OFFSET 0
#define CP500_EEPROM_CPU_SIZE 3072
#define CP500_EEPROM_USER_NAME "user_eeprom"
#define CP500_EEPROM_USER_OFFSET 3072
#define CP500_EEPROM_USER_SIZE 1024
/* SPI flash running at full speed */
#define CP500_FLASH_HZ (33 * 1000 * 1000)
/* LAN9252 */
#define CP500_LAN9252_HZ (10 * 1000 * 1000)
#define CP500_IS_CP035(dev) ((dev)->pci_dev->device == PCI_DEVICE_ID_KEBA_CP035)
#define CP500_IS_CP505(dev) ((dev)->pci_dev->device == PCI_DEVICE_ID_KEBA_CP505)
#define CP500_IS_CP520(dev) ((dev)->pci_dev->device == PCI_DEVICE_ID_KEBA_CP520)
struct cp500_dev_info {
off_t offset;
size_t size;
unsigned int msix;
};
struct cp500_devs {
struct cp500_dev_info startup;
struct cp500_dev_info spi;
struct cp500_dev_info i2c;
struct cp500_dev_info fan;
struct cp500_dev_info batt;
struct cp500_dev_info uart0_rfb;
struct cp500_dev_info uart1_dbg;
struct cp500_dev_info uart2_si1;
};
/* list of devices within FPGA of CP035 family (CP035, CP056, CP057) */
static struct cp500_devs cp035_devices = {
.startup = { 0x0000, SZ_4K },
.spi = { 0x1000, SZ_4K },
.i2c = { 0x4000, SZ_4K },
.fan = { 0x9000, SZ_4K },
.batt = { 0xA000, SZ_4K },
.uart0_rfb = { 0xB000, SZ_4K, CP500_RFB_UART_MSIX },
.uart2_si1 = { 0xD000, SZ_4K, CP500_SI1_UART_MSIX },
};
/* list of devices within FPGA of CP505 family (CP503, CP505, CP507) */
static struct cp500_devs cp505_devices = {
.startup = { 0x0000, SZ_4K },
.spi = { 0x4000, SZ_4K },
.i2c = { 0x5000, SZ_4K },
.fan = { 0x9000, SZ_4K },
.batt = { 0xA000, SZ_4K },
.uart0_rfb = { 0xB000, SZ_4K, CP500_RFB_UART_MSIX },
.uart2_si1 = { 0xD000, SZ_4K, CP500_SI1_UART_MSIX },
};
/* list of devices within FPGA of CP520 family (CP520, CP530) */
static struct cp500_devs cp520_devices = {
.startup = { 0x0000, SZ_4K },
.spi = { 0x4000, SZ_4K },
.i2c = { 0x5000, SZ_4K },
.fan = { 0x8000, SZ_4K },
.batt = { 0x9000, SZ_4K },
.uart0_rfb = { 0xC000, SZ_4K, CP500_RFB_UART_MSIX },
.uart1_dbg = { 0xD000, SZ_4K, CP500_DEBUG_UART_MSIX },
};
struct cp500_nvmem {
struct nvmem_device *base_nvmem;
unsigned int offset;
struct nvmem_device *nvmem;
};
struct cp500 {
struct pci_dev *pci_dev;
struct cp500_devs *devs;
int msix_num;
struct {
int major;
int minor;
int build;
} version;
struct notifier_block nvmem_notifier;
atomic_t nvmem_notified;
/* system FPGA BAR */
resource_size_t sys_hwbase;
struct keba_spi_auxdev *spi;
struct keba_i2c_auxdev *i2c;
struct keba_fan_auxdev *fan;
struct keba_batt_auxdev *batt;
struct keba_uart_auxdev *uart0_rfb;
struct keba_uart_auxdev *uart1_dbg;
struct keba_uart_auxdev *uart2_si1;
/* ECM EtherCAT BAR */
resource_size_t ecm_hwbase;
/* NVMEM devices */
struct cp500_nvmem nvmem_cpu;
struct cp500_nvmem nvmem_user;
void __iomem *system_startup_addr;
};
/* I2C devices */
#define CP500_EEPROM_ADDR 0x50
static struct i2c_board_info cp500_i2c_info[] = {
{ /* temperature sensor */
I2C_BOARD_INFO("emc1403", 0x4c),
},
{ /*
* CPU EEPROM
* CP035 family: CPU board
* CP505 family: bridge board
* CP520 family: carrier board
*/
I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR),
},
{ /* interface board EEPROM */
I2C_BOARD_INFO("24c3