Skip to content
Snippets Groups Projects
Commit a8988f4b authored by Clemens Terasa's avatar Clemens Terasa
Browse files

gfplatdetect: Add platform abstraction

Add a platform abstraction layer to be able to add a whole different
platform like NALLINO.

The current implementation was based on the Flash-N-Go Boot and the
previous Linux implementation for the Garz & Fricke SAN* platforms.

This however does not fit into for the NALLINO board and thus we need
new function for the new board. To be able to add a new platform
introduce the struct gfplatdetect_platform that abstracts platform
specific read function of the PFID pins and their evaluation.

Many refactoring changes were made to make the code more readable and
better structured.

Right now the NALLINO/iMX6ULL is not yet implemented.
parent 1bce0cdb
No related branches found
No related tags found
1 merge request!24Add imx6ull gfplatdetect
......@@ -27,15 +27,38 @@
#include <linux/of.h>
#include <linux/platform_device.h>
extern unsigned int imx_get_soc_revision(void);
extern unsigned int mxc_get_cpu_type(void);
#define PFID_NUM_MAX 12
#define PFID_BOARD_SANTVEND 0xf
#define PFID_BOARD_SANTARO 0x7
#define PFID_BOARD_SDC_CSPU 0x6
#define PFID_BOARD_SANTOKA 0x5
#define PFID_BOARD_SANTINO 0x4
#define PFID_BOARD_SANTINO_LT 0x3
#define PFID_BOARD_SANTVENDbat 0x2
#define PFID_BOARD_HYDRA_CPU1 0x1
#define PFID_BOARD_HYDRA_CPU2 0x0
#define PFID_BOARD_UNKNOWN 0x10
#define PFID_BOARD_FSL_SABRE 0x11
#define PFID_REV_21 0x9
#define PFID_REV_20 0xa
#define PFID_REV_14 0xb
#define PFID_REV_13 0xc
#define PFID_REV_12 0xd
#define PFID_REV_11 0xe
#define PFID_REV_10 0xf
/* Kernel exports */
extern unsigned int system_rev;
extern const char *system_serial;
extern unsigned int board_rev;
extern unsigned int fngboot_rev;
extern const char *machine_name;
extern unsigned int imx_get_soc_revision(void);
extern unsigned int mxc_get_cpu_type(void);
#define BOARD_NAME "Garz & Fricke %s (i.MX6)"
static char board_name[64] = "Garz & Fricke i.MX6";
......@@ -46,35 +69,26 @@ struct gfplatdetect_data {
const char *machine_name;
};
struct gfplatdetect_platform {
unsigned int pfid_num;
int (*get_pfids)(struct device *dev, unsigned int pfid_values);
char *(*get_model)(unsigned int pfid_board);
unsigned int (*get_board_rev)(int pfid_rev);
};
struct gfplatdetect_devdata {
struct device* dev;
struct gfplatdetect_data backup;
struct gfplatdetect_data data;
char machine_name[32];
unsigned int pfid[3];
#define PFID_BOARD 0
#define PFID_CLOCK 1
#define PFID_REV 2
const struct gfplatdetect_platform *plat;
};
#define PFID_NUM 12
#define PFID_BOARD_SANTVEND 0xf
#define PFID_BOARD_SANTARO 0x7
#define PFID_BOARD_SDC_CSPU 0x6
#define PFID_BOARD_SANTOKA 0x5
#define PFID_BOARD_SANTINO 0x4
#define PFID_BOARD_SANTINO_LT 0x3
#define PFID_BOARD_SANTVENDbat 0x2
#define PFID_BOARD_HYDRA_CPU1 0x1
#define PFID_BOARD_HYDRA_CPU2 0x0
#define PFID_BOARD_UNKNOWN 0x10
#define PFID_BOARD_FSL_SABRE 0x11
#define PFID_REV_21 0x9
#define PFID_REV_20 0xa
#define PFID_REV_14 0xb
#define PFID_REV_13 0xc
#define PFID_REV_12 0xd
#define PFID_REV_11 0xe
#define PFID_REV_10 0xf
static ssize_t board_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
......@@ -127,93 +141,145 @@ static struct attribute *gfplatdetect_attrs[] = {
&dev_attr_fngboot_rev.attr,
NULL,
};
ATTRIBUTE_GROUPS(gfplatdetect);
static int gfplatdetect_get_pfids_imx6q(struct device *dev,
unsigned int pfid_values)
{
struct gfplatdetect_devdata *devdata =
(struct gfplatdetect_devdata *) dev_get_drvdata(dev);
devdata->pfid[PFID_BOARD] = (pfid_values >> 0) & 0xF;
devdata->pfid[PFID_CLOCK] = (pfid_values >> 4) & 0xF;
devdata->pfid[PFID_REV] = (pfid_values >> 8) & 0xF;
dev_info(dev, "pfid_board: %d, pfid_clock: %d, pfid_rev: %d\n",
devdata->pfid[PFID_BOARD],
devdata->pfid[PFID_CLOCK],
devdata->pfid[PFID_REV]);
return 0;
}
static char *gfplatdetect_get_model_imx6q(unsigned int pfid_board)
{
/* Board type */
switch(pfid_board){
case PFID_BOARD_SANTVEND: return "SANTVEND";
case PFID_BOARD_SANTARO: return "SANTARO";
case PFID_BOARD_SDC_CSPU: return "SDC CSPU";
case PFID_BOARD_SANTOKA: return "SANTOKA";
case PFID_BOARD_SANTINO: return "SANTINO";
case PFID_BOARD_SANTINO_LT: return "SANTINO-LT";
case PFID_BOARD_SANTVENDbat: return "SANTVEND (bat)";
case PFID_BOARD_HYDRA_CPU1: return "HYDRA (cpu1)";
case PFID_BOARD_HYDRA_CPU2: return "HYDRA (cpu2)";
case PFID_BOARD_FSL_SABRE: return "FSL SABRE";
default:
case PFID_BOARD_UNKNOWN: return "unknown";
}
}
static unsigned int gfplatdetect_get_board_rev_imx6q(int pfid_rev)
{
/* Board revision */
switch (pfid_rev) {
default:
case PFID_REV_10: return (0x0100 << 16);
case PFID_REV_11: return (0x0101 << 16);
case PFID_REV_12: return (0x0102 << 16);
case PFID_REV_13: return (0x0103 << 16);
case PFID_REV_14: return (0x0104 << 16);
case PFID_REV_20: return (0x0200 << 16);
case PFID_REV_21: return (0x0201 << 16);
}
}
static struct gfplatdetect_platform gfplatdetect_imx6q = {
.pfid_num = 12,
.get_pfids = gfplatdetect_get_pfids_imx6q,
.get_model = gfplatdetect_get_model_imx6q,
.get_board_rev = gfplatdetect_get_board_rev_imx6q,
};
static const struct of_device_id gfplatdetect_match[] = {
{ .compatible = "guf,imx6q-platdetect", .data = &gfplatdetect_imx6q},
/* { .compatible = "guf,imx6ull-platdetect",
* .data = &gfplatdetect_imx6ull},
*/
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, gfplatdetect_match);
static int gfplatdetect_probe(struct platform_device *pdev)
{
struct gfplatdetect_devdata *devdata;
struct device *dev = &pdev->dev;
const struct of_device_id *id;
struct gpio_descs *pfid;
DECLARE_BITMAP(pfid_values, PFID_NUM);
int pfid_board, pfid_clock, pfid_rev;
DECLARE_BITMAP(pfid_values, PFID_NUM_MAX);
const char* model;
struct gfplatdetect_devdata *devdata;
char *c;
struct device_node *root;
devdata = (struct gfplatdetect_devdata*) devm_kzalloc(dev,
sizeof(struct gfplatdetect_devdata), GFP_KERNEL);
if(!devdata)
return -ENOMEM;
dev_set_drvdata(dev, devdata);
devdata->dev = dev;
id = of_match_node (gfplatdetect_match, dev->of_node);
if (!id) {
return -ENODEV;
}
if(!id->data) {
return -EINVAL;
}
devdata->plat = id->data;
pfid = devm_gpiod_get_array(dev, "pfid", GPIOD_IN);
if(IS_ERR_OR_NULL(pfid) || pfid->ndescs != PFID_NUM) {
if(IS_ERR_OR_NULL(pfid) || pfid->ndescs < devdata->plat->pfid_num) {
dev_err(dev, "Unable to get PFID GPIOs\n");
return PTR_ERR(pfid);
}
gpiod_get_array_value_cansleep(pfid->ndescs, pfid->desc, pfid->info,
pfid_values);
devm_gpiod_put_array(dev, pfid);
devdata = (struct gfplatdetect_devdata*) devm_kzalloc(dev,
sizeof(struct gfplatdetect_devdata), GFP_KERNEL);
if(!devdata)
return -ENOMEM;
dev_set_drvdata(dev, devdata);
devdata->dev = dev;
devdata->backup.system_rev = system_rev;
devdata->backup.board_rev = board_rev;
devdata->backup.fngboot_rev = fngboot_rev;
devdata->backup.machine_name = machine_name;
pfid_board = (pfid_values[0] >> 0) & 0xF;
pfid_clock = (pfid_values[0] >> 4) & 0xF;
pfid_rev = (pfid_values[0] >> 8) & 0xF;
dev_info(dev, "pfid_board: %d, pfid_clock: %d, pfid_rev: %d\n", pfid_board, pfid_clock, pfid_rev);
devdata->plat->get_pfids(dev, pfid_values[0]);
/* Board type */
switch(pfid_board){
case PFID_BOARD_SANTVEND: model = "SANTVEND"; break;
case PFID_BOARD_SANTARO: model = "SANTARO"; break;
case PFID_BOARD_SDC_CSPU: model = "SDC CSPU"; break;
case PFID_BOARD_SANTOKA: model = "SANTOKA"; break;
case PFID_BOARD_SANTINO: model = "SANTINO"; break;
case PFID_BOARD_SANTINO_LT: model = "SANTINO-LT"; break;
case PFID_BOARD_SANTVENDbat: model = "SANTVEND (bat)"; break;
case PFID_BOARD_HYDRA_CPU1: model = "HYDRA (cpu1)"; break;
case PFID_BOARD_HYDRA_CPU2: model = "HYDRA (cpu2)"; break;
case PFID_BOARD_FSL_SABRE: model = "FSL SABRE"; break;
default:
case PFID_BOARD_UNKNOWN: model = "unknown"; break;
}
model = devdata->plat->get_model(devdata->pfid[PFID_BOARD]);
snprintf(board_name, sizeof(board_name), BOARD_NAME, model);
machine_name = board_name;
strncpy(devdata->machine_name, model, sizeof(devdata->machine_name));
for (c = devdata->machine_name; *c != '\0' &&
(c - devdata->machine_name) < sizeof(devdata->machine_name);
c++) {
devdata->machine_name[sizeof(devdata->machine_name) - 1] = '\0';
for (c = devdata->machine_name; *c != '\0'; c++) {
*c=tolower(*c);
};
devdata->data.machine_name=devdata->machine_name;
/* Board revision */
switch (pfid_rev) {
default:
case PFID_REV_10: board_rev = (0x0100 << 16); break;
case PFID_REV_11: board_rev = (0x0101 << 16); break;
case PFID_REV_12: board_rev = (0x0102 << 16); break;
case PFID_REV_13: board_rev = (0x0103 << 16); break;
case PFID_REV_14: board_rev = (0x0104 << 16); break;
case PFID_REV_20: board_rev = (0x0200 << 16); break;
case PFID_REV_21: board_rev = (0x0201 << 16); break;
}
devdata->data.board_rev = board_rev;
devdata->data.board_rev = devdata->plat->get_board_rev(
devdata->pfid[PFID_REV]);
/* system_rev holds the SoC revision*/
system_rev = mxc_get_cpu_type() << 12 | imx_get_soc_revision();
devdata->data.system_rev = system_rev;
devdata->data.system_rev = mxc_get_cpu_type() << 12 |
imx_get_soc_revision();
/* FnGBoot version */
/* FnGBoot version from ATAGS revision */
root = of_find_node_by_path("/");
of_property_read_u32(root, "atag-revision", &fngboot_rev);
devdata->data.fngboot_rev = fngboot_rev;
of_property_read_u32(root, "atag-revision",
&devdata->data.fngboot_rev);
system_rev = devdata->data.system_rev;
board_rev = devdata->data.board_rev;
fngboot_rev = devdata->data.fngboot_rev;
return 0;
}
......@@ -228,10 +294,6 @@ static int gfplatdetect_remove(struct platform_device *pdev) {
return 0;
};
static const struct of_device_id gfplatdetect_match[] = {
{ .compatible = "guf,imx6q-gfplatdetect" },
{}
};
static struct platform_driver gfplatdetect_driver = {
.probe = gfplatdetect_probe,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment