Skip to content
Permalink
Browse files
HACK: mtd: spi-nor: Look for PHY pattern partition
The Cadence controller needs to know the PHY tuning pattern location to
be able to tune PHY and enable high speed operation. There is no simple
way to get that information to the controller. We have used MTD
partitions as a way to record that information.

The problem is, MTD partitions are parsed and populated after the flash
is probed. Also, the controller doesn't have direct access to the list
of mtd partitions. So SPI NOR has to find that information out during
its probe.

This patch implements a simple MTD partition parser based on
drivers/mtd/parsers/ofpart.c::parse_fixed_parititons(). This is
obviously not the place to parse the partitions and we can probably find
a better way to do this but this is the simplest way to solve this problem.

There is one obvious limitation with this approach: the partition has to
be specified in the device tree and it cannot come from the command
line.

This hack will let us use PHY tuning until we can figure out a cleaner
way of getting the tuning pattern location to the controller.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
  • Loading branch information
Pratyush Yadav committed Aug 18, 2020
1 parent 5ee294f commit 6f9db649f76819bbe6b9ee1a7758717d0f2e01ee
Showing 1 changed file with 35 additions and 2 deletions.
@@ -5561,6 +5561,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
struct device *dev = nor->dev;
struct mtd_info *mtd = &nor->mtd;
struct device_node *np = spi_nor_get_flash_node(nor);
struct device_node *child;
struct spi_nor_flash_parameter *params = &nor->params;
struct spi_mem_op op;
int ret;
@@ -5688,8 +5689,40 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
if (ret)
return ret;

op = spi_nor_spimem_read_op(nor);
spi_mem_set_calibration_read_op(nor->spimem, &op);
/*
* Find out if a PHY pattern partition is present.
*
* TODO: Teach the mtd core to find the partition for us so we don't
* have to repeat the parsing logic here that mtd already has.
*/
child = NULL;
do {
int len;
char *label = NULL;

child = of_get_next_child(np, child);
if (child)
label = (char *)of_get_property(child, "label", &len);

if (label && !strcmp(label, "ospi.phypattern")) {
const __be32 *reg;
int a_cells, s_cells;

reg = of_get_property(child, "reg", &len);
if (!reg)
continue;

a_cells = of_n_addr_cells(child);
s_cells = of_n_size_cells(child);
if (len / 4 != a_cells + s_cells)
continue;

op = spi_nor_spimem_read_op(nor);
op.addr.val = of_read_number(reg, a_cells);
spi_mem_set_calibration_read_op(nor->spimem, &op);
break;
}
} while (child);

dev_info(dev, "%s (%lld Kbytes)\n", info->name,
(long long)mtd->size >> 10);

0 comments on commit 6f9db64

Please sign in to comment.