Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
O
ohwr-build-scripts
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Dimitris Lampridis
ohwr-build-scripts
Commits
31d788f2
Commit
31d788f2
authored
5 years ago
by
Dimitris Lampridis
Browse files
Options
Downloads
Patches
Plain Diff
[fmc-sw] support EEPROM reading through at24 in post 5.0 kernels.
parent
2f6fd5e9
No related branches found
No related tags found
No related merge requests found
Pipeline
#1214225
passed
5 years ago
Stage: test
Changes
2
Pipelines
4
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
README.md
+0
-5
0 additions, 5 deletions
README.md
patches/fmc-sw.diff
+88
-78
88 additions, 78 deletions
patches/fmc-sw.diff
with
88 additions
and
83 deletions
README.md
+
0
−
5
View file @
31d788f2
...
...
@@ -15,8 +15,3 @@ errors during installation) in the following distributions:
However, there is no guarantee that things will properly work on these distributions, once
installed. In particular, there is a known issue with DMA transfers causing a kernel crash, which
prohibits for example the retrieval of ADC samples from the FMC-ADC-100M.
There is also another known issue with Linux kernels > v5.0. Due to a significant change in the at24
driver, it is no longer possible to access the SPEC/SVEC/FMC EEPROMs. The drivers have been modified
to bypass this issue and continue working when used with such a kernel, but the EEPROM will still
not be accessible.
This diff is collapsed.
Click to expand it.
patches/fmc-sw.diff
+
88
−
78
View file @
31d788f2
diff --git a/drivers/fmc/fmc-eeprom.c b/drivers/fmc/fmc-eeprom.c
index a000a0d..
e5f96b2
100644
index a000a0d..
2bd2a6f
100644
--- a/drivers/fmc/fmc-eeprom.c
+++ b/drivers/fmc/fmc-eeprom.c
@@ -10,6 +10,10 @@
@@ -7,9 +7,14 @@
#include <linux/module.h>
#include <linux/memory.h>
#include <linux/fmc.h>
+#include <linux/slab.h>
#include "fmc-internal.h"
#include "fmc-compat.h"
...
...
@@ -13,49 +17,31 @@ index a000a0d..e5f96b2 100644
#define FRU_EEPROM_NAME "fru_eeprom"
/**
@@ -17,1
2
+2
1,37
@@
@@ -17,1
1
+2
2,14
@@
*/
#define FMC_EEPROM_TYPE_DEFAULT "24c02"
+#if KERNEL_VERSION(5, 1, 0) <= LINUX_VERSION_CODE
+/* static int fmc_slot_eeprom_setup(struct notifier_block *nb, */
+/* unsigned long event, void *data) */
+/* { */
+/* struct nvmem_device *nvmem = data; */
+
+/* //dev_err(&nvmem->dev, "friendly notifier, action %ld\n", event); */
+/* if (strcmp(nvmem_dev_name(nvmem), "1-00500") != 0) */
+/* return NOTIFY_DONE; */
+
+/* return NOTIFY_OK; */
+/* }; */
+
+/* static struct notifier_block fmc_eeprom_nvmem_notifier = { */
+/* .notifier_call = fmc_slot_eeprom_setup, */
+/* }; */
+struct property_entry at24_properties[] = {
-/**
- * Setup function for the AT24C02 EEPROM. What we need to do here is to
- * quickly validate the EEPROM content. The EEPROM should contain a valid
- * FRU.
- */
+#if KERNEL_VERSION(4, 6, 0) <= LINUX_VERSION_CODE
+const struct property_entry at24_24c02[AT24_NUM_PROPERTIES] = {
+ PROPERTY_ENTRY_U32("size", 256),
+ PROPERTY_ENTRY_U32("pagesize", 8),
+ PROPERTY_ENTRY_U32("address-width", 16),
+ { }
+};
+#else
/**
* Setup function for the AT24C02 EEPROM. What we need to do here is to
* quickly validate the EEPROM content. The EEPROM should contain a valid
* FRU.
*/
+#if KERNEL_VERSION(4, 6, 0) <= LINUX_VERSION_CODE
+static void fmc_slot_eeprom_setup(struct nvmem_device *macc, void *context)
+#else
static void fmc_slot_eeprom_setup(struct memory_accessor *macc, void *context)
+#endif
{
struct fmc_slot *slot = context;
@@ -38,17 +67,26 @@
static const struct at24_platform_data at24_24c02 = {
@@ -38,9 +46,10 @@
static const struct at24_platform_data at24_24c02 = {
.flags = 0,
.setup = fmc_slot_eeprom_setup,
};
+#endif /* KERNEL_VERSION(
5
,
1
, 0) <= LINUX_VERSION_CODE */
+#endif /* KERNEL_VERSION(
4
,
6
, 0) <= LINUX_VERSION_CODE */
/**
- * Initialize I2C EEPROM info with standad values
...
...
@@ -63,68 +49,92 @@ index a000a0d..e5f96b2 100644
*/
static void fmc_slot_eeprom_init(struct fmc_slot *slot,
struct i2c_board_info *info,
const char *name)
@@ -48,7 +57,11 @@
static void fmc_slot_eeprom_init(struct fmc_slot *slot,
{
+#if KERNEL_VERSION(5, 1, 0) <= LINUX_VERSION_CODE
+ struct property_entry **p_entry;
+#endif
strncpy(info->type, name, I2C_NAME_SIZE);
info->addr = FMC_EEPROM_ADDR_SPACE;
+#if KERNEL_VERSION(5, 1, 0) <= LINUX_VERSION_CODE
+ p_entry = (struct property_entry **)&info->properties;
+ *p_entry = at24_properties;
+#if KERNEL_VERSION(4, 6, 0) <= LINUX_VERSION_CODE
+ info->properties = slot->at24_data;
+#else
info->platform_data = &slot->at24_data;
+#endif
}
static void fmc_slot_eeprom_init_default(struct fmc_slot *slot,
@@ -56,8 +9
4
,12 @@
static void fmc_slot_eeprom_init_default(struct fmc_slot *slot,
@@ -56,8 +
6
9,12 @@
static void fmc_slot_eeprom_init_default(struct fmc_slot *slot,
{
memset(info, 0, sizeof(*info));
fmc_slot_eeprom_init(slot, info, FMC_EEPROM_TYPE_DEFAULT);
+#if KERNEL_VERSION(
5
,
1
, 0) > LINUX_VERSION_CODE
+#if KERNEL_VERSION(
4
,
6
, 0) > LINUX_VERSION_CODE
memcpy(&slot->at24_data, &at24_24c02, sizeof(slot->at24_data));
slot->at24_data.context = slot;
+
/*
#else
*/
+
/* nvmem_register_notifier(&fmc_eeprom_nvmem_notifier); */
+#else
+
memcpy(slot->at24_data, &at24_24c02, sizeof(slot->at24_data));
+#endif
}
/**
@@ -70,9 +112,15 @@
ssize_t fmc_slot_eeprom_read(struct fmc_slot *slot,
@@ -66,13 +83,41 @@
static void fmc_slot_eeprom_init_default(struct fmc_slot *slot,
ssize_t fmc_slot_eeprom_read(struct fmc_slot *slot,
void *buf, off_t offset, size_t count)
{
+ int err = 0;
+#if KERNEL_VERSION(4, 6, 0) <= LINUX_VERSION_CODE
+ int idx;
+ size_t len;
+ struct nvmem_device *nvmem;
+ char *nvmem_name;
+ /*
+ * TODO Check if index can be anything else than zero and,
+ * if yes, how to get the proper value.
+ */
+ idx = 0;
+ len = strlen(dev_name(&slot->eeprom->dev)) + 2;
+ nvmem_name = kzalloc(len, GFP_KERNEL);
+ if (nvmem_name) {
+ snprintf(nvmem_name, len, "%s%d",
+ dev_name(&slot->eeprom->dev), idx);
+ nvmem = nvmem_device_get(&slot->dev, nvmem_name);
+ if (nvmem) {
+ err = nvmem_device_read(nvmem, offset, count, buf);
+#if KERNEL_VERSION(5, 1, 0) <= LINUX_VERSION_CODE
+ nvmem_device_put(nvmem);
+#endif
+ }
+ kfree(nvmem_name);
+ }
+#else
/*
* TODO if we export this function, do we have to lock it when we
* use it? Think about it
*/
- if (!slot->macc || !slot->macc->read)
+ if (!slot->macc)
+ return -ENODEV;
+#if KERNEL_VERSION(4, 6, 0) <= LINUX_VERSION_CODE
+ return nvmem_device_read(slot->macc, offset, count, buf);
+#else
+ if (!slot->macc->read)
if (!slot->macc || !slot->macc->read)
return -ENODEV;
return slot->macc->read(slot->macc, buf, offset, count);
- return slot->macc->read(slot->macc, buf, offset, count);
+ err = slot->macc->read(slot->macc, buf, offset, count);
+#endif
+ return err;
}
EXPORT_SYMBOL(fmc_slot_eeprom_read);
@@ -1
76,6 +224
,9 @@
int
fmc_slot_eeprom_
type_set
(struct fmc_slot *slot
, const char *type
)
s
truct i2c_board_info i2c_info
;
unsigned int len
;
int ret
;
+#if KERNEL_VERSION(
5
,
1
, 0)
<=
LINUX_VERSION_CODE
+
s
truct property_entry *p_entry
;
@@ -1
52,7 +197
,9 @@
void
fmc_slot_eeprom_
del
(struct fmc_slot *slot)
s
ysfs_remove_link(&slot->dev.kobj, FRU_EEPROM_NAME)
;
i2c_unregister_device(slot->eeprom)
;
slot->eeprom = NULL
;
+#if KERNEL_VERSION(
4
,
6
, 0)
>
LINUX_VERSION_CODE
s
lot->macc = NULL
;
+#endif
}
if (strncmp(type, "24c", 3)) {
if (strncmp(type, "at24c", 5)) {
@@ -197,19 +248,24 @@
int fmc_slot_eeprom_type_set(struct fmc_slot *slot, const char *type)
/**
@@ -197,19 +244,25 @@
int fmc_slot_eeprom_type_set(struct fmc_slot *slot, const char *type)
memset(&i2c_info, 0, sizeof(i2c_info));
+#if KERNEL_VERSION(
5
,
1
, 0) > LINUX_VERSION_CODE
+#if KERNEL_VERSION(
4
,
6
, 0) > LINUX_VERSION_CODE
memset(&slot->at24_data, 0, sizeof(slot->at24_data));
+#else
+ memset(slot->at24_data, 0, sizeof(slot->at24_data));
+#endif
len = (len * 1024) / 8;
...
...
@@ -137,26 +147,27 @@ index a000a0d..e5f96b2 100644
- else if (len > 131072) /* 1024K 128KiB */
+ if (len > 131072) /* 1024K 128KiB */
return -EINVAL;
+#if KERNEL_VERSION(5, 1, 0) > LINUX_VERSION_CODE
+ else if (len > 4096) /* 32K 4KiB */
+ slot->at24_data.flags = AT24_FLAG_ADDR16;
+#endif
fmc_slot_eeprom_init(slot, &i2c_info, type);
+#if KERNEL_VERSION(5, 1, 0) > LINUX_VERSION_CODE
+
+#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE
+ if (len > 4096) /* 32K 4KiB */
+ slot->at24_data.flags = AT24_FLAG_ADDR16;
slot->at24_data.byte_len = len;
slot->at24_data.page_size = 1; /* 1Byte page to play safe */
slot->at24_data.setup = fmc_slot_eeprom_setup;
@@ -219,7 +27
5
,1
2
@@
int fmc_slot_eeprom_type_set(struct fmc_slot *slot, const char *type)
@@ -219,7 +27
2
,1
5
@@
int fmc_slot_eeprom_type_set(struct fmc_slot *slot, const char *type)
i2c_info.type, i2c_info.addr,
slot->at24_data.byte_len, slot->at24_data.page_size,
slot->at24_data.flags);
-
+#else
+ p_entry = (struct property_entry *)i2c_info.properties;
+ p_entry[0] = PROPERTY_ENTRY_U32("pagesize", 1);
+ dev_dbg(&slot->dev, "%s 0x%x\n",
+ i2c_info.type, i2c_info.addr);
+ slot->at24_data[0] = PROPERTY_ENTRY_U32("size", len);
+ slot->at24_data[1] = PROPERTY_ENTRY_U32("pagesize", 1);
+ if (len > 4096) /* 32K 4KiB */
+ slot->at24_data[2] = PROPERTY_ENTRY_U32("address-width", 16);
+ dev_dbg(&slot->dev, "%s 0x%x %d\n",
+ i2c_info.type, i2c_info.addr, len);
+#endif
return fmc_slot_eeprom_replace(slot, &i2c_info);
}
...
...
@@ -185,7 +196,7 @@ index 35a1380..2fd95eb 100644
-
-#endif
diff --git a/include/linux/fmc.h b/include/linux/fmc.h
index 3bc5c12..
f99886c
100644
index 3bc5c12..
7fd835f
100644
--- a/include/linux/fmc.h
+++ b/include/linux/fmc.h
@@ -11,13 +11,13 @@
...
...
@@ -204,16 +215,15 @@ index 3bc5c12..f99886c 100644
#ifndef _LINUX_FMC_H
#define _LINUX_FMC_H
@@ -84,8 +84,1
4
@@
struct fmc_slot {
@@ -84,8 +84,1
3
@@
struct fmc_slot {
struct i2c_client *eeprom;
+#if KERNEL_VERSION(4, 6, 0) <= LINUX_VERSION_CODE
+ struct nvmem_device *macc;
+#define AT24_NUM_PROPERTIES 4
+ struct property_entry at24_data[AT24_NUM_PROPERTIES];
+#else
struct memory_accessor *macc;
+#endif
+#if KERNEL_VERSION(5, 1, 0) > LINUX_VERSION_CODE
struct at24_platform_data at24_data;
+#endif
};
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment