Commit 3e7a6262 authored by Federico Vaga's avatar Federico Vaga

Merge branch 'feature/spiflash' into develop

parents 02eb8c61 94d7d1c2
...@@ -13,6 +13,33 @@ ...@@ -13,6 +13,33 @@
#include "spec-compat.h" #include "spec-compat.h"
#include "gn412x.h" #include "gn412x.h"
#define FCL_CTRL_START_FSM BIT(0)
#define FCL_CTRL_SPRI_EN BIT(1)
#define FCL_CTRL_FSM_EN BIT(2)
#define FCL_CTRL_SEND_CFG_DATA BIT(3)
#define FCL_CTRL_LAST_BYTE_CNT_1 (0x3 << 4)
#define FCL_CTRL_LAST_BYTE_CNT_2 (0x2 << 4)
#define FCL_CTRL_LAST_BYTE_CNT_3 (0x1 << 4)
#define FCL_CTRL_LAST_BYTE_CNT_4 (0x0 << 4)
#define FCL_CTRL_RESET BIT(6)
#define FCL_CTRL_DATA_PUSH_COMP BIT(7)
#define FCL_CTRL_SPRI_CLK_STOP_EN BIT(8)
#define FCL_SPRI_CLKOUT BIT(0)
#define FCL_SPRI_DATAOUT BIT(1)
#define FCL_SPRI_CONFIG BIT(2)
#define FCL_SPRI_DONE BIT(3)
#define FCL_SPRI_XI_SWAP BIT(4)
#define FCL_SPRI_STATUS BIT(5)
#define FCL_IRQ_SPRI_STATUS BIT(0)
#define FCL_IRQ_TIMER BIT(1)
#define FCL_IRQ_CONFIG_ERROR BIT(2)
#define FCL_IRQ_CONFIG_DONE BIT(3)
#define FCL_IRQ_FIFO_UNDRFL BIT(4)
#define FCL_IRQ_FIFO_HALFFULL BIT(5)
/* Compatibility layer */ /* Compatibility layer */
static int gn412x_fcl_write_init(struct fpga_manager *mgr, static int gn412x_fcl_write_init(struct fpga_manager *mgr,
struct fpga_image_info *info, struct fpga_image_info *info,
...@@ -122,8 +149,75 @@ struct gn412x_fcl_dev { ...@@ -122,8 +149,75 @@ struct gn412x_fcl_dev {
void __iomem *mem; void __iomem *mem;
struct fpga_manager *mgr; struct fpga_manager *mgr;
struct dentry *dbg_dir;
#define GN412X_DBG_REG_NAME "regs"
struct dentry *dbg_reg;
struct debugfs_regset32 dbg_reg32;
};
#define REG32(_name, _offset) {.name = _name, .offset = _offset}
static const struct debugfs_reg32 gn412x_debugfs_reg32[] = {
REG32("FCL_CTRL", FCL_CTRL),
REG32("FCL_STATUS", FCL_STATUS),
REG32("FCL_IODATA_IN", FCL_IODATA_IN),
REG32("FCL_IODATA_OUT", FCL_IODATA_OUT),
REG32("FCL_EN", FCL_EN),
REG32("FCL_TIMER0", FCL_TIMER_0),
REG32("FCL_TIMER1", FCL_TIMER_1),
REG32("FCL_CLK_DIV", FCL_CLK_DIV),
REG32("FCL_IRQ", FCL_IRQ),
REG32("FCL_TIMER_CTRL", FCL_TIMER_CTRL),
REG32("FCL_IM", FCL_IM),
REG32("FCL_TIMER2_0", FCL_TIMER2_0),
REG32("FCL_TIMER2_1", FCL_TIMER2_1),
REG32("FCL_DBG_STS", FCL_DBG_STS),
}; };
static int gn4124_dbg_init(struct platform_device *pdev)
{
struct gn412x_fcl_dev *gn412x = platform_get_drvdata(pdev);
struct dentry *dir, *file;
int err;
dir = debugfs_create_dir(dev_name(&pdev->dev), NULL);
if (IS_ERR_OR_NULL(dir)) {
err = PTR_ERR(dir);
dev_warn(&pdev->dev,
"Cannot create debugfs directory \"%s\" (%d)\n",
dev_name(&pdev->dev), err);
goto err_dir;
}
gn412x->dbg_reg32.regs = gn412x_debugfs_reg32;
gn412x->dbg_reg32.nregs = ARRAY_SIZE(gn412x_debugfs_reg32);
gn412x->dbg_reg32.base = gn412x->mem;
file = debugfs_create_regset32(GN412X_DBG_REG_NAME, 0200,
dir, &gn412x->dbg_reg32);
if (IS_ERR_OR_NULL(file)) {
err = PTR_ERR(file);
dev_warn(&pdev->dev,
"Cannot create debugfs file \"%s\" (%d)\n",
GN412X_DBG_REG_NAME, err);
goto err_reg32;
}
gn412x->dbg_dir = dir;
gn412x->dbg_reg = file;
return 0;
err_reg32:
debugfs_remove_recursive(dir);
err_dir:
return err;
}
static void gn4124_dbg_exit(struct platform_device *pdev)
{
struct gn412x_fcl_dev *gn412x = platform_get_drvdata(pdev);
debugfs_remove_recursive(gn412x->dbg_dir);
}
static uint32_t gn412x_ioread32(struct gn412x_fcl_dev *gn412x, static uint32_t gn412x_ioread32(struct gn412x_fcl_dev *gn412x,
int reg) int reg)
{ {
...@@ -182,7 +276,6 @@ static void gn4124_fpga_reset(struct gn412x_fcl_dev *gn412x) ...@@ -182,7 +276,6 @@ static void gn4124_fpga_reset(struct gn412x_fcl_dev *gn412x)
GNPCI_SYS_CFG_SYSTEM); GNPCI_SYS_CFG_SYSTEM);
} }
/** /**
* Initialize the gennum * Initialize the gennum
* @gn412x: gn412x device instance * @gn412x: gn412x device instance
...@@ -193,31 +286,35 @@ static void gn4124_fpga_reset(struct gn412x_fcl_dev *gn412x) ...@@ -193,31 +286,35 @@ static void gn4124_fpga_reset(struct gn412x_fcl_dev *gn412x)
static int gn4124_fpga_fcl_init(struct gn412x_fcl_dev *gn412x, static int gn4124_fpga_fcl_init(struct gn412x_fcl_dev *gn412x,
int last_word_size) int last_word_size)
{ {
uint32_t ctrl; uint32_t ctrl, en;
int i; int i;
gn412x_iowrite32(gn412x, 0x00, FCL_CLK_DIV); gn412x_iowrite32(gn412x, 0x00, FCL_CLK_DIV);
gn412x_iowrite32(gn412x, 0x40, FCL_CTRL); /* Reset */ gn412x_iowrite32(gn412x, FCL_CTRL_RESET, FCL_CTRL);
i = gn412x_ioread32(gn412x, FCL_CTRL); i = gn412x_ioread32(gn412x, FCL_CTRL);
if (i != 0x40) { if (i != FCL_CTRL_RESET) {
pr_err("%s: %i: error\n", __func__, __LINE__); pr_err("%s: %i: error\n", __func__, __LINE__);
return -EIO; return -EIO;
} }
gn412x_iowrite32(gn412x, 0x00, FCL_CTRL); gn412x_iowrite32(gn412x, 0x00, FCL_CTRL);
gn412x_iowrite32(gn412x, 0x00, FCL_IRQ); /* clear pending irq */ gn412x_iowrite32(gn412x, 0x00, FCL_IRQ); /* clear pending irq */
ctrl = 0;
ctrl |= FCL_CTRL_SPRI_EN;
ctrl |= FCL_CTRL_FSM_EN;
ctrl |= FCL_CTRL_SPRI_CLK_STOP_EN;
switch (last_word_size) { switch (last_word_size) {
case 3: case 3:
ctrl = 0x116; ctrl |= FCL_CTRL_LAST_BYTE_CNT_3;
break; break;
case 2: case 2:
ctrl = 0x126; ctrl |= FCL_CTRL_LAST_BYTE_CNT_2;
break; break;
case 1: case 1:
ctrl = 0x136; ctrl |= FCL_CTRL_LAST_BYTE_CNT_1;
break; break;
case 0: case 0:
ctrl = 0x106; ctrl |= FCL_CTRL_LAST_BYTE_CNT_4;
break; break;
default: return -EINVAL; default: return -EINVAL;
} }
...@@ -233,9 +330,14 @@ static int gn4124_fpga_fcl_init(struct gn412x_fcl_dev *gn412x, ...@@ -233,9 +330,14 @@ static int gn4124_fpga_fcl_init(struct gn412x_fcl_dev *gn412x,
*/ */
gn412x_iowrite32(gn412x, 0x08, FCL_TIMER2_0); gn412x_iowrite32(gn412x, 0x08, FCL_TIMER2_0);
gn412x_iowrite32(gn412x, 0x00, FCL_TIMER2_1); gn412x_iowrite32(gn412x, 0x00, FCL_TIMER2_1);
gn412x_iowrite32(gn412x, 0x17, FCL_EN); en = 0;
en |= FCL_SPRI_CLKOUT;
ctrl |= 0x01; /* "start FSM configuration" */ en |= FCL_SPRI_DATAOUT;
en |= FCL_SPRI_CONFIG;
en |= FCL_SPRI_XI_SWAP;
gn412x_iowrite32(gn412x, en, FCL_EN);
ctrl |= FCL_CTRL_START_FSM;
gn412x_iowrite32(gn412x, ctrl, FCL_CTRL); gn412x_iowrite32(gn412x, ctrl, FCL_CTRL);
return 0; return 0;
...@@ -292,12 +394,12 @@ static int gn4124_fpga_load(struct gn412x_fcl_dev *gn412x, ...@@ -292,12 +394,12 @@ static int gn4124_fpga_load(struct gn412x_fcl_dev *gn412x,
/* Check to see if FPGA configuation has error */ /* Check to see if FPGA configuation has error */
int i = gn412x_ioread32(gn412x, FCL_IRQ); int i = gn412x_ioread32(gn412x, FCL_IRQ);
if ((i & 8) && wrote) { if ((i & FCL_IRQ_CONFIG_DONE) && wrote) {
done = 1; done = 1;
pr_err("%s: %i: done after %i%i\n", pr_err("%s: %i: done after %i%i\n",
__func__, __LINE__, __func__, __LINE__,
wrote, ((len + 3) >> 2)); wrote, ((len + 3) >> 2));
} else if ((i & 0x4) && !done) { } else if ((i & FCL_IRQ_CONFIG_ERROR) && !done) {
pr_err("%s: %i: error after %i/%i\n", pr_err("%s: %i: error after %i/%i\n",
__func__, __LINE__, __func__, __LINE__,
wrote, ((len + 3) >> 2)); wrote, ((len + 3) >> 2));
...@@ -305,7 +407,7 @@ static int gn4124_fpga_load(struct gn412x_fcl_dev *gn412x, ...@@ -305,7 +407,7 @@ static int gn4124_fpga_load(struct gn412x_fcl_dev *gn412x,
} }
/* Wait until at least 1/2 of the fifo is empty */ /* Wait until at least 1/2 of the fifo is empty */
while (gn412x_ioread32(gn412x, FCL_IRQ) & (1<<5)) while (gn412x_ioread32(gn412x, FCL_IRQ) & FCL_IRQ_FIFO_HALFFULL)
; ;
/* Write a few dwords into FIFO at a time. */ /* Write a few dwords into FIFO at a time. */
...@@ -326,7 +428,13 @@ static int gn4124_fpga_load(struct gn412x_fcl_dev *gn412x, ...@@ -326,7 +428,13 @@ static int gn4124_fpga_load(struct gn412x_fcl_dev *gn412x,
*/ */
static void gn4124_fpga_fcl_complete(struct gn412x_fcl_dev *gn412x) static void gn4124_fpga_fcl_complete(struct gn412x_fcl_dev *gn412x)
{ {
gn412x_iowrite32(gn412x, 0x186, FCL_CTRL); /* "last data written" */ uint32_t ctrl = 0;
ctrl |= FCL_CTRL_SPRI_EN;
ctrl |= FCL_CTRL_FSM_EN;
ctrl |= FCL_CTRL_DATA_PUSH_COMP;
ctrl |= FCL_CTRL_SPRI_CLK_STOP_EN;
gn412x_iowrite32(gn412x, ctrl, FCL_CTRL);
} }
...@@ -363,6 +471,12 @@ static int gn412x_fcl_write(struct fpga_manager *mgr, ...@@ -363,6 +471,12 @@ static int gn412x_fcl_write(struct fpga_manager *mgr,
} }
static void gn4124_fcl_reset(struct gn412x_fcl_dev *gn412x)
{
gn412x_iowrite32(gn412x, 0x00, FCL_CTRL);
gn412x_iowrite32(gn412x, 0x00, FCL_EN);
}
static int gn412x_fcl_write_complete(struct fpga_manager *mgr, static int gn412x_fcl_write_complete(struct fpga_manager *mgr,
struct fpga_image_info *info) struct fpga_image_info *info)
{ {
...@@ -375,6 +489,7 @@ static int gn412x_fcl_write_complete(struct fpga_manager *mgr, ...@@ -375,6 +489,7 @@ static int gn412x_fcl_write_complete(struct fpga_manager *mgr,
if (err < 0) if (err < 0)
return err; return err;
gn4124_fcl_reset(gn412x);
gn4124_fpga_reset(gn412x); gn4124_fpga_reset(gn412x);
return 0; return 0;
...@@ -421,6 +536,9 @@ static int gn412x_fcl_probe(struct platform_device *pdev) ...@@ -421,6 +536,9 @@ static int gn412x_fcl_probe(struct platform_device *pdev)
goto err_map; goto err_map;
} }
gn4124_fcl_reset(gn412x);
gn4124_dbg_init(pdev);
gn412x->mgr = compat_fpga_mgr_create(&pdev->dev, gn412x->mgr = compat_fpga_mgr_create(&pdev->dev,
dev_name(&pdev->dev), dev_name(&pdev->dev),
...@@ -439,6 +557,7 @@ static int gn412x_fcl_probe(struct platform_device *pdev) ...@@ -439,6 +557,7 @@ static int gn412x_fcl_probe(struct platform_device *pdev)
err_fpga_reg: err_fpga_reg:
compat_fpga_mgr_free(gn412x->mgr); compat_fpga_mgr_free(gn412x->mgr);
err_fpga_create: err_fpga_create:
gn4124_dbg_exit(pdev);
devm_iounmap(&pdev->dev, gn412x->mem); devm_iounmap(&pdev->dev, gn412x->mem);
err_map: err_map:
err_res_mem: err_res_mem:
...@@ -450,6 +569,8 @@ static int gn412x_fcl_remove(struct platform_device *pdev) ...@@ -450,6 +569,8 @@ static int gn412x_fcl_remove(struct platform_device *pdev)
{ {
struct gn412x_fcl_dev *gn412x = platform_get_drvdata(pdev); struct gn412x_fcl_dev *gn412x = platform_get_drvdata(pdev);
gn4124_dbg_exit(pdev);
if (!gn412x->mgr) if (!gn412x->mgr)
return -ENODEV; return -ENODEV;
......
...@@ -323,10 +323,12 @@ static struct resource spec_fpga_fmc_i2c_res[] = { ...@@ -323,10 +323,12 @@ static struct resource spec_fpga_fmc_i2c_res[] = {
}, },
}; };
#define SPEC_FPGA_WB_CLK_HZ 62500000
#define SPEC_FPGA_WB_CLK_KHZ (SPEC_FPGA_WB_CLK_HZ / 1000)
static struct ocores_i2c_platform_data spec_fpga_fmc_i2c_pdata = { static struct ocores_i2c_platform_data spec_fpga_fmc_i2c_pdata = {
.reg_shift = 2, /* 32bit aligned */ .reg_shift = 2, /* 32bit aligned */
.reg_io_width = 4, .reg_io_width = 4,
.clock_khz = 62500, .clock_khz = SPEC_FPGA_WB_CLK_KHZ,
.big_endian = 0, .big_endian = 0,
.num_devices = 0, .num_devices = 0,
.devices = NULL, .devices = NULL,
...@@ -356,7 +358,7 @@ struct flash_platform_data spec_flash_pdata = { ...@@ -356,7 +358,7 @@ struct flash_platform_data spec_flash_pdata = {
static struct spi_board_info spec_fpga_spi_devices_info[] = { static struct spi_board_info spec_fpga_spi_devices_info[] = {
{ {
.modalias = "m25p32", .modalias = "m25p32",
.max_speed_hz = 75000000, .max_speed_hz = SPEC_FPGA_WB_CLK_HZ / 128,
.chip_select = 0, .chip_select = 0,
.platform_data = &spec_flash_pdata, .platform_data = &spec_flash_pdata,
} }
...@@ -364,7 +366,7 @@ static struct spi_board_info spec_fpga_spi_devices_info[] = { ...@@ -364,7 +366,7 @@ static struct spi_board_info spec_fpga_spi_devices_info[] = {
static struct spi_ocores_platform_data spec_fpga_spi_pdata = { static struct spi_ocores_platform_data spec_fpga_spi_pdata = {
.big_endian = 0, .big_endian = 0,
.clock_hz = 65200000, .clock_hz = SPEC_FPGA_WB_CLK_HZ,
.num_devices = ARRAY_SIZE(spec_fpga_spi_devices_info), .num_devices = ARRAY_SIZE(spec_fpga_spi_devices_info),
.devices = spec_fpga_spi_devices_info, .devices = spec_fpga_spi_devices_info,
}; };
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment