[PATCH v2] mtd/spi-nor: Add SPI memory controllers for Aspeed SoCs

Marek Vasut marek.vasut at gmail.com
Thu Dec 8 18:29:48 PST 2016


On 12/08/2016 05:36 PM, Cédric Le Goater wrote:
> Hello Marek,

Hi!

[...]

>>> @@ -0,0 +1,72 @@
>>> +* Aspeed Static Memory controller
>>> +* Aspeed SPI Flash Controller
>>> +
>>> +The Static memory controller in the ast2400 supports 5 chip selects
>>> +each can be attached to NAND, parallel NOR, or SPI NOR attached flash.
>>
>> So this controller is supported by this driver, which behaves like a SPI
>> controller driver, yet the block can also do NAND and parallel NOR ?
> 
> I think that was answered in a previous email.

Yep, thanks!

>>> +The Firmware Memory Controller in the ast2500 supports 3 chip selects,
>>> +two of which are always in SPI-NOR mode and the third can be SPI-NOR
>>> +or parallel flash. The SPI flash controller in the ast2400 supports
>>> +one of 2 chip selects selected by pinmux. The two SPI flash
>>> +controllers in the ast2500 each support two chip selects.
>>
>> This paragraph is confusing, it's hard to grok down how many different
>> controllers does this driver support and what are their properties from
>> it. It is all there, it's just hard to read.
> 
> I will start with the AST2500 controllers only, which are consistent.

That works too :-)

[...]

>>> +	tristate "Aspeed flash controllers in SPI mode"
>>> +	depends on HAS_IOMEM && OF
>>> +	depends on ARCH_ASPEED || COMPILE_TEST
>>> +	# IO_SPACE_LIMIT must be equivalent to (~0UL)
>>> +	depends on !NEED_MACH_IO_H
>>
>> Why?
> 
> Some left over from the patch we have been keeping for too long (+1year)
> in our tree.

Hehe, I see, so it's fixed now.

>>> +	help
>>> +	  This enables support for the New Static Memory Controller
>>> +	  (FMC) in the Aspeed SoCs (AST2400 and AST2500) when attached
>>> +	  to SPI nor chips, and support for the SPI Memory controller
>>> +	  (SPI) for the BIOS.
>>
>> I think there is a naming chaos between FMC, SMC (as in Static MC) and
>> SMC (as in SPI MC).
> 
> I agree, I will try to clarify the naming in the next version. I will keep 
> the smc suffix for the driver name though.

Thanks!

[...]

>>> +static void aspeed_smc_chip_set_4b_smc_2400(struct aspeed_smc_chip *chip);
>>> +static void aspeed_smc_chip_set_4b(struct aspeed_smc_chip *chip);
>>> +
>>> +static const struct aspeed_smc_info fmc_2400_info = {
>>> +	.maxsize = 64 * 1024 * 1024,
>>> +	.nce = 5,
>>> +	.maxwidth = 4,
>>> +	.hastype = true,
>>
>> Shouldn't all this be specified in DT ?
> 
> I am not sure, these values are not configurable. I will remove a few 
> of them in the next version as they are unused.

Sooo, I had a discussion with Boris (which we didn't finish yet).
Please ignore my comment for now and yes please, drop unused params.

>>> +	.we0 = 16,
>>> +	.ctl0 = 0x10,
>>> +	.time = 0x94,
>>> +	.misc = 0x54,
>>> +	.set_4b = aspeed_smc_chip_set_4b,
>>> +};

[...]

>>> +static u32 spi_control_fill_opcode(u8 opcode)
>>> +{
>>> +	return ((u32)(opcode)) << CONTROL_SPI_COMMAND_SHIFT;
>>
>> return opcode << CONTROL... , fix these horrible casts and parenthesis
>> globally.
> 
> I killed the helper. 

Nice, thanks for all the cleanups :)

>>> +}
>>> +
>>> +static inline u32 aspeed_smc_chip_write_bit(struct aspeed_smc_chip *chip)
>>> +{
>>> +	return ((u32)1 << (chip->controller->info->we0 + chip->cs));
>>
>> return BIT(...)
>>
>> I'm not sure these microfunctions are even needed.
> 
> well, this one is used in a couple of places.

Ah all right, then just return BIT(...) and be done with it.

>>> +}

[...]

>>> +static int aspeed_smc_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
>>> +{
>>> +	struct aspeed_smc_chip *chip = nor->priv;
>>> +
>>> +	mutex_lock(&chip->controller->mutex);
>>
>> Won't this have a horrid overhead ?
> 
> Shall I use the prepare() and unprepare() ops instead ? 

I think that'd trim down the amount of locking, yes.

>>> +	aspeed_smc_start_user(nor);
>>> +	aspeed_smc_write_to_ahb(chip->base, &opcode, 1);
>>> +	aspeed_smc_read_from_ahb(buf, chip->base, len);
>>> +	aspeed_smc_stop_user(nor);
>>> +
>>> +	mutex_unlock(&chip->controller->mutex);
>>> +
>>> +	return 0;
>>> +}

[...]

>>> +static int aspeed_smc_chip_setup_init(struct aspeed_smc_chip *chip,
>>> +				      struct resource *r)
>>> +{
>>> +	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 for the moment */
>>> +	if (info->hastype)
>>> +		aspeed_smc_chip_set_type(chip, smc_type_spi);
>>> +
>>> +	/*
>>> +	 * Configure chip base address in memory
>>> +	 */
>>> +	chip->base = window_start(controller, r, chip->cs);
>>> +	if (!chip->base) {
>>> +		dev_warn(chip->nor.dev, "CE segment window closed.\n");
>>> +		return -1;
>>> +	}
>>> +
>>> +	/*
>>> +	 * Read the existing control register to get basic values.
>>> +	 *
>>> +	 * XXX This register probably needs more sanitation.
>>
>> What's this comment about ?
> 
> This is an initial comment about settings being done by U-Boot
> before the kernel is loaded, and some optimisations should be 
> nice to keep, for the FMC controller. I will rephrase.

Shouldn't that be passed via DT instead ? We want to be bootloader
agnostic in Linux.

btw off-topic, but is U-Boot support for these aspeed devices ever be
upstreamed ?

>>> +	 * Do we need support for mode 3 vs mode 0 clock phasing?
>>> +	 */
>>> +	reg = readl(chip->ctl);
>>> +	dev_dbg(controller->dev, "control register: %08x\n", reg);
>>> +
>>> +	base_reg = reg & CONTROL_SPI_KEEP_MASK;
>>> +	if (base_reg != reg) {
>>> +		dev_info(controller->dev,
>>> +			 "control register changed to: %08x\n",
>>> +			 base_reg);
>>> +	}


[...]

>>> +		err = mtd_device_register(&chip->nor.mtd, NULL, 0);
>>> +		if (err)
>>> +			continue;
>>
>> What happens if some chip fails to register ?
> 
> That's not correctly handled ... I have a fix for it.
> 
> Thanks,

Thanks for all the work :)

-- 
Best regards,
Marek Vasut



More information about the linux-mtd mailing list