[PATCH v3 1/5] mtd: spi-nor: add memory controllers for the Aspeed AST2500 SoC
Marek Vasut
marek.vasut at gmail.com
Fri Dec 9 20:01:56 PST 2016
On 12/09/2016 05:49 PM, Cédric Le Goater wrote:
[...]
> +static int aspeed_smc_read_from_ahb(void *buf, const void __iomem *src,
> + size_t len)
> +{
> + if (IS_ALIGNED((u32)src, sizeof(u32)) &&
> + IS_ALIGNED((u32)buf, sizeof(u32)) &&
> + IS_ALIGNED(len, sizeof(u32))) {
Did you try compiling this on any 64bit system ?
> + while (len > 3) {
> + *(u32 *)buf = readl(src);
ioread32_rep() to avoid open-coding the loop .
> + buf += 4;
> + src += 4;
> + len -= 4;
> + }
> + }
> +
> + while (len--) {
> + *(u8 *)buf = readb(src);
> + buf += 1;
> + src += 1;
> + }
> + return 0;
> +}
> +
> +static int aspeed_smc_write_to_ahb(void __iomem *dst, const void *buf,
> + size_t len)
> +{
> + if (IS_ALIGNED((u32)dst, sizeof(u32)) &&
> + IS_ALIGNED((u32)buf, sizeof(u32)) &&
> + IS_ALIGNED(len, sizeof(u32))) {
> + while (len > 3) {
> + u32 val = *(u32 *)buf;
> +
> + writel(val, dst);
iowrite32_rep()
> + buf += 4;
> + dst += 4;
> + len -= 4;
> + }
> + }
> +
> + while (len--) {
> + u8 val = *(u8 *)buf;
> +
> + writeb(val, dst);
> + buf += 1;
> + dst += 1;
> + }
> + return 0;
> +}
> +
> +/*
> + * The driver only support SPI flash
> + */
> +enum aspeed_smc_flash_type {
> + smc_type_nor = 0,
> + smc_type_nand = 1,
> + smc_type_spi = 2,
> +};
> +
> +struct aspeed_smc_chip;
> +
> +struct aspeed_smc_info {
> + u32 maxsize; /* maximum size of chip window */
> + u8 nce; /* number of chip enables */
> + bool hastype; /* flash type field exists in config reg */
> + u8 we0; /* shift for write enable bit for CE0 */
> + u8 ctl0; /* offset in regs of ctl for CE0 */
> +
> + void (*set_4b)(struct aspeed_smc_chip *chip);
> +};
Move all the structs to the beginning of the driver please.
> +static void aspeed_smc_chip_set_4b(struct aspeed_smc_chip *chip);
> +
> +static const struct aspeed_smc_info fmc_2500_info = {
> + .maxsize = 256 * 1024 * 1024,
> + .nce = 3,
> + .hastype = true,
> + .we0 = 16,
> + .ctl0 = 0x10,
> + .set_4b = aspeed_smc_chip_set_4b,
> +};
> +
> +static const struct aspeed_smc_info spi_2500_info = {
> + .maxsize = 128 * 1024 * 1024,
> + .nce = 2,
> + .hastype = false,
> + .we0 = 16,
> + .ctl0 = 0x10,
> + .set_4b = aspeed_smc_chip_set_4b,
> +};
> +
> +enum aspeed_smc_ctl_reg_value {
> + smc_base, /* base value without mode for other commands */
> + smc_read, /* command reg for (maybe fast) reads */
> + smc_write, /* command reg for writes */
> + smc_max,
> +};
[...]
> +#define CONTROL_CE_STOP_ACTIVE_CONTROL BIT(2)
> +#define CONTROL_COMMAND_MODE_MASK GENMASK(1, 0)
> +#define CONTROL_COMMAND_MODE_NORMAL (0)
> +#define CONTROL_COMMAND_MODE_FREAD (1)
> +#define CONTROL_COMMAND_MODE_WRITE (2)
> +#define CONTROL_COMMAND_MODE_USER (3)
Drop the parenthesis around constants :)
> +#define CONTROL_KEEP_MASK \
> + (CONTROL_AAF_MODE | CONTROL_CE_INACTIVE_MASK | CONTROL_CLK_DIV4 | \
> + CONTROL_IO_DUMMY_MASK | CONTROL_CLOCK_FREQ_SEL_MASK | \
> + CONTROL_LSB_FIRST | CONTROL_CLOCK_MODE_3)
> +
> +/*
> + * Segment Address Registers. Start and end addresses are encoded
> + * using 8MB units
> + */
> +#define SEGMENT_ADDR_REG0 0x30
> +#define SEGMENT_ADDR_START(_r) ((((_r) >> 16) & 0xFF) << 23)
is that ((r) & 0xff0000) << 7 ?
> +#define SEGMENT_ADDR_END(_r) ((((_r) >> 24) & 0xFF) << 23)
((r) & 0xff000000) >> 1 ?
> +static inline u32 aspeed_smc_chip_write_bit(struct aspeed_smc_chip *chip)
> +{
> + return BIT(chip->controller->info->we0 + chip->cs);
> +}
[...]
> +static int aspeed_smc_chip_setup_init(struct aspeed_smc_chip *chip,
> + struct resource *res)
> +{
> + struct aspeed_smc_controller *controller = chip->controller;
> + const struct aspeed_smc_info *info = controller->info;
> + u32 reg, base_reg;
> +
> + /*
> + * Always turn on the write enable bit to allow opcodes to be
> + * sent in user mode.
> + */
> + aspeed_smc_chip_enable_write(chip);
> +
> + /* The driver only supports SPI type flash */
> + if (info->hastype)
> + aspeed_smc_chip_set_type(chip, smc_type_spi);
> +
> + /*
> + * Configure chip base address in memory
> + */
> + chip->ahb_base = aspeed_smc_chip_base(chip, res);
> + if (!chip->ahb_base) {
> + dev_warn(chip->nor.dev, "CE segment window closed.\n");
> + return -1;
return -EINVAL ? Check whether you always use errno.h macros in returns.
> + }
> +
> + /*
> + * Get value of the inherited control register. U-Boot usually
> + * does some timing calibration on the FMC chip, so it's good
> + * to keep them. In the future, we should handle calibration
> + * from Linux.
> + */
> + reg = readl(chip->ctl);
> + dev_dbg(controller->dev, "control register: %08x\n", reg);
> +
> + base_reg = reg & CONTROL_KEEP_MASK;
> + if (base_reg != reg) {
> + dev_info(controller->dev,
> + "control register changed to: %08x\n",
> + base_reg);
> + }
> + chip->ctl_val[smc_base] = base_reg;
[...]
Mostly minor nits, looks nice otherwise, thanks :)
--
Best regards,
Marek Vasut
More information about the linux-mtd
mailing list